Auto merge of #100677 - matthiaskrgr:rollup-au41ho1, r=matthiaskrgr
Rollup of 15 pull requests Successful merges: - #99474 (Rustdoc json tests: New `@hasexact` test command) - #99972 (interpret: only consider 1-ZST when searching for receiver) - #100018 (Clean up `LitKind`) - #100379 (triagebot: add translation-related mention groups) - #100389 (Do not report cycle error when inferring return type for suggestion) - #100489 (`is_knowable` use `Result` instead of `Option`) - #100532 (unwind: don't build dependency when building for Miri) - #100608 (needless separation of impl blocks) - #100621 (Pass +atomics-32 feature for {arm,thumb}v4t-none-eabi) - #100646 (Migrate emoji identifier diagnostics to `SessionDiagnostic` in rustc_interface) - #100652 (Remove deferred sized checks (make them eager)) - #100655 (Update books) - #100656 (Update cargo) - #100660 (Fixed a few documentation errors) - #100661 (Fixed a few documentation errors) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
9c20b2a8cc
84 changed files with 585 additions and 422 deletions
|
@ -321,7 +321,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cargo"
|
||||
version = "0.65.0"
|
||||
version = "0.66.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"atty",
|
||||
|
@ -4011,6 +4011,7 @@ dependencies = [
|
|||
"rustc_hir",
|
||||
"rustc_incremental",
|
||||
"rustc_lint",
|
||||
"rustc_macros",
|
||||
"rustc_metadata",
|
||||
"rustc_middle",
|
||||
"rustc_mir_build",
|
||||
|
@ -4359,6 +4360,7 @@ dependencies = [
|
|||
"rustc_serialize",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
|
|
|
@ -1689,7 +1689,7 @@ pub enum StrStyle {
|
|||
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
pub struct Lit {
|
||||
/// The original literal token as written in source code.
|
||||
pub token: token::Lit,
|
||||
pub token_lit: token::Lit,
|
||||
/// The "semantic" representation of the literal lowered from the original tokens.
|
||||
/// Strings are unescaped, hexadecimal forms are eliminated, etc.
|
||||
/// FIXME: Remove this and only create the semantic representation during lowering to HIR.
|
||||
|
@ -1717,7 +1717,7 @@ impl StrLit {
|
|||
StrStyle::Raw(n) => token::StrRaw(n),
|
||||
};
|
||||
Lit {
|
||||
token: token::Lit::new(token_kind, self.symbol, self.suffix),
|
||||
token_lit: token::Lit::new(token_kind, self.symbol, self.suffix),
|
||||
span: self.span,
|
||||
kind: LitKind::Str(self.symbol_unescaped, self.style),
|
||||
}
|
||||
|
|
|
@ -184,13 +184,7 @@ impl MetaItem {
|
|||
}
|
||||
|
||||
pub fn value_str(&self) -> Option<Symbol> {
|
||||
match self.kind {
|
||||
MetaItemKind::NameValue(ref v) => match v.kind {
|
||||
LitKind::Str(ref s, _) => Some(*s),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
self.kind.value_str()
|
||||
}
|
||||
|
||||
pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> {
|
||||
|
|
|
@ -23,7 +23,7 @@ pub enum LitError {
|
|||
|
||||
impl LitKind {
|
||||
/// Converts literal token into a semantic literal.
|
||||
pub fn from_lit_token(lit: token::Lit) -> Result<LitKind, LitError> {
|
||||
pub fn from_token_lit(lit: token::Lit) -> Result<LitKind, LitError> {
|
||||
let token::Lit { kind, symbol, suffix } = lit;
|
||||
if suffix.is_some() && !kind.may_have_suffix() {
|
||||
return Err(LitError::InvalidSuffix);
|
||||
|
@ -153,7 +153,7 @@ impl LitKind {
|
|||
/// Attempts to recover a token from semantic literal.
|
||||
/// This function is used when the original token doesn't exist (e.g. the literal is created
|
||||
/// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing).
|
||||
pub fn to_lit_token(&self) -> token::Lit {
|
||||
pub fn to_token_lit(&self) -> token::Lit {
|
||||
let (kind, symbol, suffix) = match *self {
|
||||
LitKind::Str(symbol, ast::StrStyle::Cooked) => {
|
||||
// Don't re-intern unless the escaped string is different.
|
||||
|
@ -208,8 +208,8 @@ impl LitKind {
|
|||
|
||||
impl Lit {
|
||||
/// Converts literal token into an AST literal.
|
||||
pub fn from_lit_token(token: token::Lit, span: Span) -> Result<Lit, LitError> {
|
||||
Ok(Lit { token, kind: LitKind::from_lit_token(token)?, span })
|
||||
pub fn from_token_lit(token_lit: token::Lit, span: Span) -> Result<Lit, LitError> {
|
||||
Ok(Lit { token_lit, kind: LitKind::from_token_lit(token_lit)?, span })
|
||||
}
|
||||
|
||||
/// Converts arbitrary token into an AST literal.
|
||||
|
@ -232,21 +232,21 @@ impl Lit {
|
|||
_ => return Err(LitError::NotLiteral),
|
||||
};
|
||||
|
||||
Lit::from_lit_token(lit, token.span)
|
||||
Lit::from_token_lit(lit, token.span)
|
||||
}
|
||||
|
||||
/// Attempts to recover an AST literal from semantic literal.
|
||||
/// This function is used when the original token doesn't exist (e.g. the literal is created
|
||||
/// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing).
|
||||
pub fn from_lit_kind(kind: LitKind, span: Span) -> Lit {
|
||||
Lit { token: kind.to_lit_token(), kind, span }
|
||||
Lit { token_lit: kind.to_token_lit(), kind, span }
|
||||
}
|
||||
|
||||
/// Losslessly convert an AST literal into a token.
|
||||
pub fn to_token(&self) -> Token {
|
||||
let kind = match self.token.kind {
|
||||
token::Bool => token::Ident(self.token.symbol, false),
|
||||
_ => token::Literal(self.token),
|
||||
let kind = match self.token_lit.kind {
|
||||
token::Bool => token::Ident(self.token_lit.symbol, false),
|
||||
_ => token::Literal(self.token_lit),
|
||||
};
|
||||
Token::new(kind, self.span)
|
||||
}
|
||||
|
|
|
@ -927,7 +927,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
lit.clone()
|
||||
} else {
|
||||
Lit {
|
||||
token: token::Lit::new(token::LitKind::Err, kw::Empty, None),
|
||||
token_lit: token::Lit::new(token::LitKind::Err, kw::Empty, None),
|
||||
kind: LitKind::Err(kw::Empty),
|
||||
span: DUMMY_SP,
|
||||
}
|
||||
|
|
|
@ -372,7 +372,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
|
|||
|
||||
fn print_literal(&mut self, lit: &ast::Lit) {
|
||||
self.maybe_print_comment(lit.span.lo());
|
||||
self.word(lit.token.to_string())
|
||||
self.word(lit.token_lit.to_string())
|
||||
}
|
||||
|
||||
fn print_string(&mut self, st: &str, style: ast::StrStyle) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use rustc_ast as ast;
|
||||
use rustc_ast::{ptr::P, tokenstream::TokenStream};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_expand::base::{self, DummyResult};
|
||||
|
||||
|
@ -185,5 +184,5 @@ pub fn expand_concat_bytes(
|
|||
return base::MacEager::expr(DummyResult::raw_expr(sp, true));
|
||||
}
|
||||
let sp = cx.with_def_site_ctxt(sp);
|
||||
base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(Lrc::from(accumulator))))
|
||||
base::MacEager::expr(cx.expr_byte_str(sp, accumulator))
|
||||
}
|
||||
|
|
|
@ -126,9 +126,9 @@ fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool {
|
|||
}
|
||||
|
||||
fn report_unexpected_literal(sess: &Session, lit: &ast::Lit) {
|
||||
let help_msg = match lit.token.kind {
|
||||
token::Str if rustc_lexer::is_ident(lit.token.symbol.as_str()) => {
|
||||
format!("try using `#[derive({})]`", lit.token.symbol)
|
||||
let help_msg = match lit.token_lit.kind {
|
||||
token::Str if rustc_lexer::is_ident(lit.token_lit.symbol.as_str()) => {
|
||||
format!("try using `#[derive({})]`", lit.token_lit.symbol)
|
||||
}
|
||||
_ => "for example, write `#[derive(Debug)]` for `Debug`".to_string(),
|
||||
};
|
||||
|
|
|
@ -52,7 +52,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
|
|||
|
||||
// We want to make sure we have the ctxt set so that we can use unstable methods
|
||||
let span = cx.with_def_site_ctxt(span);
|
||||
let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked));
|
||||
let name = cx.expr_str(span, ident.name);
|
||||
let fmt = substr.nonselflike_args[0].clone();
|
||||
|
||||
// Struct and tuples are similar enough that we use the same code for both,
|
||||
|
@ -89,10 +89,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
|
|||
for i in 0..fields.len() {
|
||||
let field = &fields[i];
|
||||
if is_struct {
|
||||
let name = cx.expr_lit(
|
||||
field.span,
|
||||
ast::LitKind::Str(field.name.unwrap().name, ast::StrStyle::Cooked),
|
||||
);
|
||||
let name = cx.expr_str(field.span, field.name.unwrap().name);
|
||||
args.push(name);
|
||||
}
|
||||
// Use an extra indirection to make sure this works for unsized types.
|
||||
|
@ -108,10 +105,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
|
|||
|
||||
for field in fields {
|
||||
if is_struct {
|
||||
name_exprs.push(cx.expr_lit(
|
||||
field.span,
|
||||
ast::LitKind::Str(field.name.unwrap().name, ast::StrStyle::Cooked),
|
||||
));
|
||||
name_exprs.push(cx.expr_str(field.span, field.name.unwrap().name));
|
||||
}
|
||||
|
||||
// Use an extra indirection to make sure this works for unsized types.
|
||||
|
|
|
@ -923,7 +923,7 @@ impl<'a, 'b> Context<'a, 'b> {
|
|||
}
|
||||
|
||||
// Build the format
|
||||
let fill = self.ecx.expr_lit(sp, ast::LitKind::Char(fill));
|
||||
let fill = self.ecx.expr_char(sp, fill);
|
||||
let align = |name| {
|
||||
let mut p = Context::rtpath(self.ecx, sym::Alignment);
|
||||
p.push(Ident::new(name, sp));
|
||||
|
|
|
@ -216,7 +216,7 @@ pub fn expand_include_bytes(
|
|||
}
|
||||
};
|
||||
match cx.source_map().load_binary_file(&file) {
|
||||
Ok(bytes) => base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(bytes.into()))),
|
||||
Ok(bytes) => base::MacEager::expr(cx.expr_byte_str(sp, bytes)),
|
||||
Err(e) => {
|
||||
cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e));
|
||||
DummyResult::any(sp)
|
||||
|
|
|
@ -15,7 +15,7 @@ use rustc_data_structures::profiling::TimingGuard;
|
|||
use rustc_data_structures::profiling::VerboseTimingGuard;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::emitter::Emitter;
|
||||
use rustc_errors::{DiagnosticId, FatalError, Handler, Level};
|
||||
use rustc_errors::{translation::Translate, DiagnosticId, FatalError, Handler, Level};
|
||||
use rustc_fs_util::link_or_copy;
|
||||
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
|
||||
use rustc_incremental::{
|
||||
|
@ -1740,6 +1740,16 @@ impl SharedEmitter {
|
|||
}
|
||||
}
|
||||
|
||||
impl Translate for SharedEmitter {
|
||||
fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
|
||||
panic!("shared emitter attempted to translate a diagnostic");
|
||||
}
|
||||
}
|
||||
|
||||
impl Emitter for SharedEmitter {
|
||||
fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) {
|
||||
let fluent_args = self.to_fluent_args(diag.args());
|
||||
|
@ -1761,14 +1771,6 @@ impl Emitter for SharedEmitter {
|
|||
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
|
||||
panic!("shared emitter attempted to translate a diagnostic");
|
||||
}
|
||||
}
|
||||
|
||||
impl SharedEmitterMain {
|
||||
|
|
|
@ -534,7 +534,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
let mut non_zst_field = None;
|
||||
for i in 0..receiver.layout.fields.count() {
|
||||
let field = self.operand_field(&receiver, i)?;
|
||||
if !field.layout.is_zst() {
|
||||
let zst =
|
||||
field.layout.is_zst() && field.layout.align.abi.bytes() == 1;
|
||||
if !zst {
|
||||
assert!(
|
||||
non_zst_field.is_none(),
|
||||
"multiple non-ZST fields in dyn receiver type {}",
|
||||
|
|
|
@ -56,9 +56,7 @@ cfg_if! {
|
|||
pub fn new(v: T) -> Self {
|
||||
Atomic(Cell::new(v))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> Atomic<T> {
|
||||
#[inline]
|
||||
pub fn into_inner(self) -> T {
|
||||
self.0.into_inner()
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
interface_ferris_identifier =
|
||||
Ferris cannot be used as an identifier
|
||||
.suggestion = try using their name instead
|
||||
|
||||
interface_emoji_identifier =
|
||||
identifiers cannot contain emoji: `{$ident}`
|
|
@ -34,6 +34,7 @@ fluent_messages! {
|
|||
builtin_macros => "../locales/en-US/builtin_macros.ftl",
|
||||
const_eval => "../locales/en-US/const_eval.ftl",
|
||||
expand => "../locales/en-US/expand.ftl",
|
||||
interface => "../locales/en-US/interface.ftl",
|
||||
lint => "../locales/en-US/lint.ftl",
|
||||
parser => "../locales/en-US/parser.ftl",
|
||||
passes => "../locales/en-US/passes.ftl",
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
use crate::emitter::FileWithAnnotatedLines;
|
||||
use crate::snippet::Line;
|
||||
use crate::translation::Translate;
|
||||
use crate::{
|
||||
CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, Emitter, FluentBundle,
|
||||
LazyFallbackBundle, Level, MultiSpan, Style, SubDiagnostic,
|
||||
|
@ -32,6 +33,16 @@ pub struct AnnotateSnippetEmitterWriter {
|
|||
macro_backtrace: bool,
|
||||
}
|
||||
|
||||
impl Translate for AnnotateSnippetEmitterWriter {
|
||||
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
|
||||
self.fluent_bundle.as_ref()
|
||||
}
|
||||
|
||||
fn fallback_fluent_bundle(&self) -> &FluentBundle {
|
||||
&**self.fallback_bundle
|
||||
}
|
||||
}
|
||||
|
||||
impl Emitter for AnnotateSnippetEmitterWriter {
|
||||
/// The entry point for the diagnostics generation
|
||||
fn emit_diagnostic(&mut self, diag: &Diagnostic) {
|
||||
|
@ -63,14 +74,6 @@ impl Emitter for AnnotateSnippetEmitterWriter {
|
|||
self.source_map.as_ref()
|
||||
}
|
||||
|
||||
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
|
||||
self.fluent_bundle.as_ref()
|
||||
}
|
||||
|
||||
fn fallback_fluent_bundle(&self) -> &FluentBundle {
|
||||
&**self.fallback_bundle
|
||||
}
|
||||
|
||||
fn should_show_explain(&self) -> bool {
|
||||
!self.short_message
|
||||
}
|
||||
|
|
|
@ -14,10 +14,10 @@ use rustc_span::{FileLines, SourceFile, Span};
|
|||
|
||||
use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, Style, StyledString};
|
||||
use crate::styled_buffer::StyledBuffer;
|
||||
use crate::translation::Translate;
|
||||
use crate::{
|
||||
CodeSuggestion, Diagnostic, DiagnosticArg, DiagnosticId, DiagnosticMessage, FluentBundle,
|
||||
Handler, LazyFallbackBundle, Level, MultiSpan, SubDiagnostic, SubstitutionHighlight,
|
||||
SuggestionStyle,
|
||||
CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, FluentBundle, Handler,
|
||||
LazyFallbackBundle, Level, MultiSpan, SubDiagnostic, SubstitutionHighlight, SuggestionStyle,
|
||||
};
|
||||
|
||||
use rustc_lint_defs::pluralize;
|
||||
|
@ -200,7 +200,7 @@ impl Margin {
|
|||
const ANONYMIZED_LINE_NUM: &str = "LL";
|
||||
|
||||
/// Emitter trait for emitting errors.
|
||||
pub trait Emitter {
|
||||
pub trait Emitter: Translate {
|
||||
/// Emit a structured diagnostic.
|
||||
fn emit_diagnostic(&mut self, diag: &Diagnostic);
|
||||
|
||||
|
@ -231,102 +231,6 @@ pub trait Emitter {
|
|||
|
||||
fn source_map(&self) -> Option<&Lrc<SourceMap>>;
|
||||
|
||||
/// Return `FluentBundle` with localized diagnostics for the locale requested by the user. If no
|
||||
/// language was requested by the user then this will be `None` and `fallback_fluent_bundle`
|
||||
/// should be used.
|
||||
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>>;
|
||||
|
||||
/// Return `FluentBundle` with localized diagnostics for the default locale of the compiler.
|
||||
/// Used when the user has not requested a specific language or when a localized diagnostic is
|
||||
/// unavailable for the requested locale.
|
||||
fn fallback_fluent_bundle(&self) -> &FluentBundle;
|
||||
|
||||
/// Convert diagnostic arguments (a rustc internal type that exists to implement
|
||||
/// `Encodable`/`Decodable`) into `FluentArgs` which is necessary to perform translation.
|
||||
///
|
||||
/// Typically performed once for each diagnostic at the start of `emit_diagnostic` and then
|
||||
/// passed around as a reference thereafter.
|
||||
fn to_fluent_args<'arg>(&self, args: &[DiagnosticArg<'arg>]) -> FluentArgs<'arg> {
|
||||
FromIterator::from_iter(args.to_vec().drain(..))
|
||||
}
|
||||
|
||||
/// Convert `DiagnosticMessage`s to a string, performing translation if necessary.
|
||||
fn translate_messages(
|
||||
&self,
|
||||
messages: &[(DiagnosticMessage, Style)],
|
||||
args: &FluentArgs<'_>,
|
||||
) -> Cow<'_, str> {
|
||||
Cow::Owned(
|
||||
messages.iter().map(|(m, _)| self.translate_message(m, args)).collect::<String>(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Convert a `DiagnosticMessage` to a string, performing translation if necessary.
|
||||
fn translate_message<'a>(
|
||||
&'a self,
|
||||
message: &'a DiagnosticMessage,
|
||||
args: &'a FluentArgs<'_>,
|
||||
) -> Cow<'_, str> {
|
||||
trace!(?message, ?args);
|
||||
let (identifier, attr) = match message {
|
||||
DiagnosticMessage::Str(msg) => return Cow::Borrowed(&msg),
|
||||
DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
|
||||
};
|
||||
|
||||
let translate_with_bundle = |bundle: &'a FluentBundle| -> Option<(Cow<'_, str>, Vec<_>)> {
|
||||
let message = bundle.get_message(&identifier)?;
|
||||
let value = match attr {
|
||||
Some(attr) => message.get_attribute(attr)?.value(),
|
||||
None => message.value()?,
|
||||
};
|
||||
debug!(?message, ?value);
|
||||
|
||||
let mut errs = vec![];
|
||||
let translated = bundle.format_pattern(value, Some(&args), &mut errs);
|
||||
debug!(?translated, ?errs);
|
||||
Some((translated, errs))
|
||||
};
|
||||
|
||||
self.fluent_bundle()
|
||||
.and_then(|bundle| translate_with_bundle(bundle))
|
||||
// If `translate_with_bundle` returns `None` with the primary bundle, this is likely
|
||||
// just that the primary bundle doesn't contain the message being translated, so
|
||||
// proceed to the fallback bundle.
|
||||
//
|
||||
// However, when errors are produced from translation, then that means the translation
|
||||
// is broken (e.g. `{$foo}` exists in a translation but `foo` isn't provided).
|
||||
//
|
||||
// In debug builds, assert so that compiler devs can spot the broken translation and
|
||||
// fix it..
|
||||
.inspect(|(_, errs)| {
|
||||
debug_assert!(
|
||||
errs.is_empty(),
|
||||
"identifier: {:?}, attr: {:?}, args: {:?}, errors: {:?}",
|
||||
identifier,
|
||||
attr,
|
||||
args,
|
||||
errs
|
||||
);
|
||||
})
|
||||
// ..otherwise, for end users, an error about this wouldn't be useful or actionable, so
|
||||
// just hide it and try with the fallback bundle.
|
||||
.filter(|(_, errs)| errs.is_empty())
|
||||
.or_else(|| translate_with_bundle(self.fallback_fluent_bundle()))
|
||||
.map(|(translated, errs)| {
|
||||
// Always bail out for errors with the fallback bundle.
|
||||
assert!(
|
||||
errs.is_empty(),
|
||||
"identifier: {:?}, attr: {:?}, args: {:?}, errors: {:?}",
|
||||
identifier,
|
||||
attr,
|
||||
args,
|
||||
errs
|
||||
);
|
||||
translated
|
||||
})
|
||||
.expect("failed to find message in primary or fallback fluent bundles")
|
||||
}
|
||||
|
||||
/// Formats the substitutions of the primary_span
|
||||
///
|
||||
/// There are a lot of conditions to this method, but in short:
|
||||
|
@ -616,11 +520,7 @@ pub trait Emitter {
|
|||
}
|
||||
}
|
||||
|
||||
impl Emitter for EmitterWriter {
|
||||
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
||||
self.sm.as_ref()
|
||||
}
|
||||
|
||||
impl Translate for EmitterWriter {
|
||||
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
|
||||
self.fluent_bundle.as_ref()
|
||||
}
|
||||
|
@ -628,6 +528,12 @@ impl Emitter for EmitterWriter {
|
|||
fn fallback_fluent_bundle(&self) -> &FluentBundle {
|
||||
&**self.fallback_bundle
|
||||
}
|
||||
}
|
||||
|
||||
impl Emitter for EmitterWriter {
|
||||
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
||||
self.sm.as_ref()
|
||||
}
|
||||
|
||||
fn emit_diagnostic(&mut self, diag: &Diagnostic) {
|
||||
let fluent_args = self.to_fluent_args(diag.args());
|
||||
|
@ -672,11 +578,7 @@ pub struct SilentEmitter {
|
|||
pub fatal_note: Option<String>,
|
||||
}
|
||||
|
||||
impl Emitter for SilentEmitter {
|
||||
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
||||
None
|
||||
}
|
||||
|
||||
impl Translate for SilentEmitter {
|
||||
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
|
||||
None
|
||||
}
|
||||
|
@ -684,6 +586,12 @@ impl Emitter for SilentEmitter {
|
|||
fn fallback_fluent_bundle(&self) -> &FluentBundle {
|
||||
panic!("silent emitter attempted to translate message")
|
||||
}
|
||||
}
|
||||
|
||||
impl Emitter for SilentEmitter {
|
||||
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn emit_diagnostic(&mut self, d: &Diagnostic) {
|
||||
if d.level == Level::Fatal {
|
||||
|
|
|
@ -13,6 +13,7 @@ use rustc_span::source_map::{FilePathMapping, SourceMap};
|
|||
|
||||
use crate::emitter::{Emitter, HumanReadableErrorType};
|
||||
use crate::registry::Registry;
|
||||
use crate::translation::Translate;
|
||||
use crate::DiagnosticId;
|
||||
use crate::{
|
||||
CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, SubDiagnostic,
|
||||
|
@ -122,6 +123,16 @@ impl JsonEmitter {
|
|||
}
|
||||
}
|
||||
|
||||
impl Translate for JsonEmitter {
|
||||
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
|
||||
self.fluent_bundle.as_ref()
|
||||
}
|
||||
|
||||
fn fallback_fluent_bundle(&self) -> &FluentBundle {
|
||||
&**self.fallback_bundle
|
||||
}
|
||||
}
|
||||
|
||||
impl Emitter for JsonEmitter {
|
||||
fn emit_diagnostic(&mut self, diag: &crate::Diagnostic) {
|
||||
let data = Diagnostic::from_errors_diagnostic(diag, self);
|
||||
|
@ -189,14 +200,6 @@ impl Emitter for JsonEmitter {
|
|||
Some(&self.sm)
|
||||
}
|
||||
|
||||
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
|
||||
self.fluent_bundle.as_ref()
|
||||
}
|
||||
|
||||
fn fallback_fluent_bundle(&self) -> &FluentBundle {
|
||||
&**self.fallback_bundle
|
||||
}
|
||||
|
||||
fn should_show_explain(&self) -> bool {
|
||||
!matches!(self.json_rendered, HumanReadableErrorType::Short(_))
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@ mod lock;
|
|||
pub mod registry;
|
||||
mod snippet;
|
||||
mod styled_buffer;
|
||||
pub mod translation;
|
||||
|
||||
pub use snippet::Style;
|
||||
|
||||
|
|
103
compiler/rustc_errors/src/translation.rs
Normal file
103
compiler/rustc_errors/src/translation.rs
Normal file
|
@ -0,0 +1,103 @@
|
|||
use crate::snippet::Style;
|
||||
use crate::{DiagnosticArg, DiagnosticMessage, FluentBundle};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_error_messages::FluentArgs;
|
||||
use std::borrow::Cow;
|
||||
|
||||
pub trait Translate {
|
||||
/// Return `FluentBundle` with localized diagnostics for the locale requested by the user. If no
|
||||
/// language was requested by the user then this will be `None` and `fallback_fluent_bundle`
|
||||
/// should be used.
|
||||
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>>;
|
||||
|
||||
/// Return `FluentBundle` with localized diagnostics for the default locale of the compiler.
|
||||
/// Used when the user has not requested a specific language or when a localized diagnostic is
|
||||
/// unavailable for the requested locale.
|
||||
fn fallback_fluent_bundle(&self) -> &FluentBundle;
|
||||
|
||||
/// Convert diagnostic arguments (a rustc internal type that exists to implement
|
||||
/// `Encodable`/`Decodable`) into `FluentArgs` which is necessary to perform translation.
|
||||
///
|
||||
/// Typically performed once for each diagnostic at the start of `emit_diagnostic` and then
|
||||
/// passed around as a reference thereafter.
|
||||
fn to_fluent_args<'arg>(&self, args: &[DiagnosticArg<'arg>]) -> FluentArgs<'arg> {
|
||||
FromIterator::from_iter(args.to_vec().drain(..))
|
||||
}
|
||||
|
||||
/// Convert `DiagnosticMessage`s to a string, performing translation if necessary.
|
||||
fn translate_messages(
|
||||
&self,
|
||||
messages: &[(DiagnosticMessage, Style)],
|
||||
args: &FluentArgs<'_>,
|
||||
) -> Cow<'_, str> {
|
||||
Cow::Owned(
|
||||
messages.iter().map(|(m, _)| self.translate_message(m, args)).collect::<String>(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Convert a `DiagnosticMessage` to a string, performing translation if necessary.
|
||||
fn translate_message<'a>(
|
||||
&'a self,
|
||||
message: &'a DiagnosticMessage,
|
||||
args: &'a FluentArgs<'_>,
|
||||
) -> Cow<'_, str> {
|
||||
trace!(?message, ?args);
|
||||
let (identifier, attr) = match message {
|
||||
DiagnosticMessage::Str(msg) => return Cow::Borrowed(&msg),
|
||||
DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
|
||||
};
|
||||
|
||||
let translate_with_bundle = |bundle: &'a FluentBundle| -> Option<(Cow<'_, str>, Vec<_>)> {
|
||||
let message = bundle.get_message(&identifier)?;
|
||||
let value = match attr {
|
||||
Some(attr) => message.get_attribute(attr)?.value(),
|
||||
None => message.value()?,
|
||||
};
|
||||
debug!(?message, ?value);
|
||||
|
||||
let mut errs = vec![];
|
||||
let translated = bundle.format_pattern(value, Some(&args), &mut errs);
|
||||
debug!(?translated, ?errs);
|
||||
Some((translated, errs))
|
||||
};
|
||||
|
||||
self.fluent_bundle()
|
||||
.and_then(|bundle| translate_with_bundle(bundle))
|
||||
// If `translate_with_bundle` returns `None` with the primary bundle, this is likely
|
||||
// just that the primary bundle doesn't contain the message being translated, so
|
||||
// proceed to the fallback bundle.
|
||||
//
|
||||
// However, when errors are produced from translation, then that means the translation
|
||||
// is broken (e.g. `{$foo}` exists in a translation but `foo` isn't provided).
|
||||
//
|
||||
// In debug builds, assert so that compiler devs can spot the broken translation and
|
||||
// fix it..
|
||||
.inspect(|(_, errs)| {
|
||||
debug_assert!(
|
||||
errs.is_empty(),
|
||||
"identifier: {:?}, attr: {:?}, args: {:?}, errors: {:?}",
|
||||
identifier,
|
||||
attr,
|
||||
args,
|
||||
errs
|
||||
);
|
||||
})
|
||||
// ..otherwise, for end users, an error about this wouldn't be useful or actionable, so
|
||||
// just hide it and try with the fallback bundle.
|
||||
.filter(|(_, errs)| errs.is_empty())
|
||||
.or_else(|| translate_with_bundle(self.fallback_fluent_bundle()))
|
||||
.map(|(translated, errs)| {
|
||||
// Always bail out for errors with the fallback bundle.
|
||||
assert!(
|
||||
errs.is_empty(),
|
||||
"identifier: {:?}, attr: {:?}, args: {:?}, errors: {:?}",
|
||||
identifier,
|
||||
attr,
|
||||
args,
|
||||
errs
|
||||
);
|
||||
translated
|
||||
})
|
||||
.expect("failed to find message in primary or fallback fluent bundles")
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ use crate::base::ExtCtxt;
|
|||
use rustc_ast::attr;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, PatKind, UnOp};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
|
||||
|
@ -330,23 +331,38 @@ impl<'a> ExtCtxt<'a> {
|
|||
self.expr_struct(span, self.path_ident(span, id), fields)
|
||||
}
|
||||
|
||||
pub fn expr_lit(&self, span: Span, lit_kind: ast::LitKind) -> P<ast::Expr> {
|
||||
fn expr_lit(&self, span: Span, lit_kind: ast::LitKind) -> P<ast::Expr> {
|
||||
let lit = ast::Lit::from_lit_kind(lit_kind, span);
|
||||
self.expr(span, ast::ExprKind::Lit(lit))
|
||||
}
|
||||
|
||||
pub fn expr_usize(&self, span: Span, i: usize) -> P<ast::Expr> {
|
||||
self.expr_lit(
|
||||
span,
|
||||
ast::LitKind::Int(i as u128, ast::LitIntType::Unsigned(ast::UintTy::Usize)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn expr_u32(&self, sp: Span, u: u32) -> P<ast::Expr> {
|
||||
self.expr_lit(sp, ast::LitKind::Int(u as u128, ast::LitIntType::Unsigned(ast::UintTy::U32)))
|
||||
}
|
||||
|
||||
pub fn expr_bool(&self, sp: Span, value: bool) -> P<ast::Expr> {
|
||||
self.expr_lit(sp, ast::LitKind::Bool(value))
|
||||
}
|
||||
|
||||
pub fn expr_str(&self, sp: Span, s: Symbol) -> P<ast::Expr> {
|
||||
self.expr_lit(sp, ast::LitKind::Str(s, ast::StrStyle::Cooked))
|
||||
}
|
||||
|
||||
pub fn expr_char(&self, sp: Span, ch: char) -> P<ast::Expr> {
|
||||
self.expr_lit(sp, ast::LitKind::Char(ch))
|
||||
}
|
||||
|
||||
pub fn expr_byte_str(&self, sp: Span, bytes: Vec<u8>) -> P<ast::Expr> {
|
||||
self.expr_lit(sp, ast::LitKind::ByteStr(Lrc::from(bytes)))
|
||||
}
|
||||
|
||||
/// `[expr1, expr2, ...]`
|
||||
pub fn expr_array(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr> {
|
||||
self.expr(sp, ast::ExprKind::Array(exprs))
|
||||
|
@ -357,10 +373,6 @@ impl<'a> ExtCtxt<'a> {
|
|||
self.expr_addr_of(sp, self.expr_array(sp, exprs))
|
||||
}
|
||||
|
||||
pub fn expr_str(&self, sp: Span, s: Symbol) -> P<ast::Expr> {
|
||||
self.expr_lit(sp, ast::LitKind::Str(s, ast::StrStyle::Cooked))
|
||||
}
|
||||
|
||||
pub fn expr_cast(&self, sp: Span, expr: P<ast::Expr>, ty: P<ast::Ty>) -> P<ast::Expr> {
|
||||
self.expr(sp, ast::ExprKind::Cast(expr, ty))
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ fn parse_depth<'sess>(
|
|||
"meta-variable expression depth must be a literal"
|
||||
));
|
||||
};
|
||||
if let Ok(lit_kind) = LitKind::from_lit_token(*lit)
|
||||
if let Ok(lit_kind) = LitKind::from_token_lit(*lit)
|
||||
&& let LitKind::Int(n_u128, LitIntType::Unsuffixed) = lit_kind
|
||||
&& let Ok(n_usize) = usize::try_from(n_u128)
|
||||
{
|
||||
|
|
|
@ -486,20 +486,26 @@ impl server::TokenStream for Rustc<'_, '_> {
|
|||
// We don't use `TokenStream::from_ast` as the tokenstream currently cannot
|
||||
// be recovered in the general case.
|
||||
match &expr.kind {
|
||||
ast::ExprKind::Lit(l) if l.token.kind == token::Bool => Ok(
|
||||
tokenstream::TokenStream::token_alone(token::Ident(l.token.symbol, false), l.span),
|
||||
),
|
||||
ast::ExprKind::Lit(l) if l.token_lit.kind == token::Bool => {
|
||||
Ok(tokenstream::TokenStream::token_alone(
|
||||
token::Ident(l.token_lit.symbol, false),
|
||||
l.span,
|
||||
))
|
||||
}
|
||||
ast::ExprKind::Lit(l) => {
|
||||
Ok(tokenstream::TokenStream::token_alone(token::Literal(l.token), l.span))
|
||||
Ok(tokenstream::TokenStream::token_alone(token::Literal(l.token_lit), l.span))
|
||||
}
|
||||
ast::ExprKind::Unary(ast::UnOp::Neg, e) => match &e.kind {
|
||||
ast::ExprKind::Lit(l) => match l.token {
|
||||
ast::ExprKind::Lit(l) => match l.token_lit {
|
||||
token::Lit { kind: token::Integer | token::Float, .. } => {
|
||||
Ok(Self::TokenStream::from_iter([
|
||||
// FIXME: The span of the `-` token is lost when
|
||||
// parsing, so we cannot faithfully recover it here.
|
||||
tokenstream::TokenTree::token_alone(token::BinOp(token::Minus), e.span),
|
||||
tokenstream::TokenTree::token_alone(token::Literal(l.token), l.span),
|
||||
tokenstream::TokenTree::token_alone(
|
||||
token::Literal(l.token_lit),
|
||||
l.span,
|
||||
),
|
||||
]))
|
||||
}
|
||||
_ => Err(()),
|
||||
|
|
|
@ -1247,7 +1247,7 @@ impl<'a> State<'a> {
|
|||
|
||||
fn print_literal(&mut self, lit: &hir::Lit) {
|
||||
self.maybe_print_comment(lit.span.lo());
|
||||
self.word(lit.node.to_lit_token().to_string())
|
||||
self.word(lit.node.to_token_lit().to_string())
|
||||
}
|
||||
|
||||
fn print_inline_asm(&mut self, asm: &hir::InlineAsm<'_>) {
|
||||
|
|
|
@ -17,6 +17,7 @@ rustc_attr = { path = "../rustc_attr" }
|
|||
rustc_borrowck = { path = "../rustc_borrowck" }
|
||||
rustc_builtin_macros = { path = "../rustc_builtin_macros" }
|
||||
rustc_expand = { path = "../rustc_expand" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_parse = { path = "../rustc_parse" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
|
|
|
@ -8,11 +8,12 @@ use rustc_borrowck as mir_borrowck;
|
|||
use rustc_codegen_ssa::traits::CodegenBackend;
|
||||
use rustc_data_structures::parallel;
|
||||
use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
|
||||
use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, PResult};
|
||||
use rustc_errors::{ErrorGuaranteed, PResult};
|
||||
use rustc_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand};
|
||||
use rustc_hir::def_id::StableCrateId;
|
||||
use rustc_hir::definitions::Definitions;
|
||||
use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore};
|
||||
use rustc_macros::SessionDiagnostic;
|
||||
use rustc_metadata::creader::CStore;
|
||||
use rustc_middle::arena::Arena;
|
||||
use rustc_middle::dep_graph::DepGraph;
|
||||
|
@ -30,7 +31,7 @@ use rustc_session::output::filename_for_input;
|
|||
use rustc_session::search_paths::PathKind;
|
||||
use rustc_session::{Limit, Session};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_span::FileName;
|
||||
use rustc_span::{FileName, Span};
|
||||
use rustc_trait_selection::traits;
|
||||
use rustc_typeck as typeck;
|
||||
use tracing::{info, warn};
|
||||
|
@ -263,6 +264,23 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error(interface::ferris_identifier)]
|
||||
struct FerrisIdentifier {
|
||||
#[primary_span]
|
||||
spans: Vec<Span>,
|
||||
#[suggestion(code = "ferris", applicability = "maybe-incorrect")]
|
||||
first_span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error(interface::emoji_identifier)]
|
||||
struct EmojiIdentifier {
|
||||
#[primary_span]
|
||||
spans: Vec<Span>,
|
||||
ident: Symbol,
|
||||
}
|
||||
|
||||
/// Runs the "early phases" of the compiler: initial `cfg` processing, loading compiler plugins,
|
||||
/// syntax expansion, secondary `cfg` expansion, synthesis of a test
|
||||
/// harness if one is to be provided, injection of a dependency on the
|
||||
|
@ -443,23 +461,9 @@ pub fn configure_and_expand(
|
|||
spans.sort();
|
||||
if ident == sym::ferris {
|
||||
let first_span = spans[0];
|
||||
sess.diagnostic()
|
||||
.struct_span_err(
|
||||
MultiSpan::from(spans),
|
||||
"Ferris cannot be used as an identifier",
|
||||
)
|
||||
.span_suggestion(
|
||||
first_span,
|
||||
"try using their name instead",
|
||||
"ferris",
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
sess.emit_err(FerrisIdentifier { spans, first_span });
|
||||
} else {
|
||||
sess.diagnostic().span_err(
|
||||
MultiSpan::from(spans),
|
||||
&format!("identifiers cannot contain emoji: `{}`", ident),
|
||||
);
|
||||
sess.emit_err(EmojiIdentifier { spans, ident });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -120,8 +120,8 @@ impl EarlyLintPass for HiddenUnicodeCodepoints {
|
|||
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
|
||||
// byte strings are already handled well enough by `EscapeError::NonAsciiCharInByteString`
|
||||
let (text, span, padding) = match &expr.kind {
|
||||
ast::ExprKind::Lit(ast::Lit { token, kind, span }) => {
|
||||
let text = token.symbol;
|
||||
ast::ExprKind::Lit(ast::Lit { token_lit, kind, span }) => {
|
||||
let text = token_lit.symbol;
|
||||
if !contains_text_flow_control_chars(text.as_str()) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -770,6 +770,7 @@ rustc_queries! {
|
|||
desc { |tcx| "computing function signature of `{}`", tcx.def_path_str(key) }
|
||||
cache_on_disk_if { key.is_local() }
|
||||
separate_provide_extern
|
||||
cycle_delay_bug
|
||||
}
|
||||
|
||||
/// Performs lint checking for the module.
|
||||
|
|
|
@ -1750,8 +1750,8 @@ impl<'a> Parser<'a> {
|
|||
Some(lit) => match lit.kind {
|
||||
ast::LitKind::Str(symbol_unescaped, style) => Ok(ast::StrLit {
|
||||
style,
|
||||
symbol: lit.token.symbol,
|
||||
suffix: lit.token.suffix,
|
||||
symbol: lit.token_lit.symbol,
|
||||
suffix: lit.token_lit.suffix,
|
||||
span: lit.span,
|
||||
symbol_unescaped,
|
||||
}),
|
||||
|
@ -1828,7 +1828,7 @@ impl<'a> Parser<'a> {
|
|||
let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None);
|
||||
let symbol = Symbol::intern(&suffixless_lit.to_string());
|
||||
let lit = token::Lit::new(token::Err, symbol, lit.suffix);
|
||||
Some(Lit::from_lit_token(lit, span).unwrap_or_else(|_| unreachable!()))
|
||||
Some(Lit::from_token_lit(lit, span).unwrap_or_else(|_| unreachable!()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ rustc_query_system = { path = "../rustc_query_system" }
|
|||
rustc_serialize = { path = "../rustc_serialize" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
rustc_target = { path = "../rustc_target" }
|
||||
tracing = "0.1"
|
||||
|
||||
[features]
|
||||
|
|
|
@ -43,3 +43,23 @@ impl<'tcx> Value<'tcx> for AdtSizedConstraint<'_> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Value<'tcx> for ty::Binder<'_, ty::FnSig<'_>> {
|
||||
fn from_cycle_error(tcx: QueryCtxt<'tcx>) -> Self {
|
||||
let err = tcx.ty_error();
|
||||
// FIXME(compiler-errors): It would be nice if we could get the
|
||||
// query key, so we could at least generate a fn signature that
|
||||
// has the right arity.
|
||||
let fn_sig = ty::Binder::dummy(tcx.mk_fn_sig(
|
||||
[].into_iter(),
|
||||
err,
|
||||
false,
|
||||
rustc_hir::Unsafety::Normal,
|
||||
rustc_target::spec::abi::Abi::Rust,
|
||||
));
|
||||
|
||||
// SAFETY: This is never called when `Self` is not `ty::Binder<'tcx, ty::FnSig<'tcx>>`.
|
||||
// FIXME: Represent the above fact in the trait system somehow.
|
||||
unsafe { std::mem::transmute::<ty::PolyFnSig<'tcx>, ty::Binder<'_, ty::FnSig<'_>>>(fn_sig) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,9 @@ pub fn target() -> Target {
|
|||
linker_flavor: LinkerFlavor::Ld,
|
||||
linker: Some("arm-none-eabi-ld".into()),
|
||||
asm_args: cvs!["-mthumb-interwork", "-march=armv4t", "-mlittle-endian",],
|
||||
features: "+soft-float,+strict-align".into(),
|
||||
// Force-enable 32-bit atomics, which allows the use of atomic load/store only.
|
||||
// The resulting atomics are ABI incompatible with atomics backed by libatomic.
|
||||
features: "+soft-float,+strict-align,+atomics-32".into(),
|
||||
main_needs_argc_argv: false,
|
||||
atomic_cas: false,
|
||||
has_thumb_interworking: true,
|
||||
|
|
|
@ -47,7 +47,9 @@ pub fn target() -> Target {
|
|||
asm_args: cvs!["-mthumb-interwork", "-march=armv4t", "-mlittle-endian",],
|
||||
|
||||
// minimum extra features, these cannot be disabled via -C
|
||||
features: "+soft-float,+strict-align".into(),
|
||||
// Also force-enable 32-bit atomics, which allows the use of atomic load/store only.
|
||||
// The resulting atomics are ABI incompatible with atomics backed by libatomic.
|
||||
features: "+soft-float,+strict-align,+atomics-32".into(),
|
||||
|
||||
panic_strategy: PanicStrategy::Abort,
|
||||
relocation_model: RelocModel::Static,
|
||||
|
|
|
@ -404,12 +404,12 @@ fn resolve_negative_obligation<'cx, 'tcx>(
|
|||
pub fn trait_ref_is_knowable<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
trait_ref: ty::TraitRef<'tcx>,
|
||||
) -> Option<Conflict> {
|
||||
) -> Result<(), Conflict> {
|
||||
debug!("trait_ref_is_knowable(trait_ref={:?})", trait_ref);
|
||||
if orphan_check_trait_ref(tcx, trait_ref, InCrate::Remote).is_ok() {
|
||||
// A downstream or cousin crate is allowed to implement some
|
||||
// substitution of this trait-ref.
|
||||
return Some(Conflict::Downstream);
|
||||
return Err(Conflict::Downstream);
|
||||
}
|
||||
|
||||
if trait_ref_is_local_or_fundamental(tcx, trait_ref) {
|
||||
|
@ -418,7 +418,7 @@ pub fn trait_ref_is_knowable<'tcx>(
|
|||
// allowed to implement a substitution of this trait ref, which
|
||||
// means impls could only come from dependencies of this crate,
|
||||
// which we already know about.
|
||||
return None;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// This is a remote non-fundamental trait, so if another crate
|
||||
|
@ -431,10 +431,10 @@ pub fn trait_ref_is_knowable<'tcx>(
|
|||
// we are an owner.
|
||||
if orphan_check_trait_ref(tcx, trait_ref, InCrate::Local).is_ok() {
|
||||
debug!("trait_ref_is_knowable: orphan check passed");
|
||||
None
|
||||
Ok(())
|
||||
} else {
|
||||
debug!("trait_ref_is_knowable: nonlocal, nonfundamental, unowned");
|
||||
Some(Conflict::Upstream)
|
||||
Err(Conflict::Upstream)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
&mut self,
|
||||
stack: &TraitObligationStack<'o, 'tcx>,
|
||||
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
|
||||
if let Some(conflict) = self.is_knowable(stack) {
|
||||
if let Err(conflict) = self.is_knowable(stack) {
|
||||
debug!("coherence stage: not knowable");
|
||||
if self.intercrate_ambiguity_causes.is_some() {
|
||||
debug!("evaluate_stack: intercrate_ambiguity_causes is some");
|
||||
|
|
|
@ -1265,11 +1265,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
Ok(Some(candidate))
|
||||
}
|
||||
|
||||
fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Option<Conflict> {
|
||||
fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Result<(), Conflict> {
|
||||
debug!("is_knowable(intercrate={:?})", self.intercrate);
|
||||
|
||||
if !self.intercrate || stack.obligation.polarity() == ty::ImplPolarity::Negative {
|
||||
return None;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let obligation = &stack.obligation;
|
||||
|
|
|
@ -561,16 +561,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// We just want to check sizedness, so instead of introducing
|
||||
// placeholder lifetimes with probing, we just replace higher lifetimes
|
||||
// with fresh vars.
|
||||
let span = args.get(i).map(|a| a.span).unwrap_or(expr.span);
|
||||
let arg_span = args.get(i).map(|a| a.span);
|
||||
let span = arg_span.unwrap_or(expr.span);
|
||||
let input = self.replace_bound_vars_with_fresh_vars(
|
||||
span,
|
||||
infer::LateBoundRegionConversionTime::FnCall,
|
||||
fn_sig.input(i),
|
||||
);
|
||||
self.require_type_is_sized_deferred(
|
||||
input,
|
||||
self.require_type_is_sized(
|
||||
self.normalize_associated_types_in(span, input),
|
||||
span,
|
||||
traits::SizedArgumentType(None),
|
||||
traits::SizedArgumentType(arg_span),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -585,7 +586,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
infer::LateBoundRegionConversionTime::FnCall,
|
||||
fn_sig.output(),
|
||||
);
|
||||
self.require_type_is_sized_deferred(output, expr.span, traits::SizedReturnType);
|
||||
self.require_type_is_sized(
|
||||
self.normalize_associated_types_in(expr.span, output),
|
||||
expr.span,
|
||||
traits::SizedReturnType,
|
||||
);
|
||||
}
|
||||
|
||||
// We always require that the type provided as the value for
|
||||
|
|
|
@ -442,17 +442,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn require_type_is_sized_deferred(
|
||||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
code: traits::ObligationCauseCode<'tcx>,
|
||||
) {
|
||||
if !ty.references_error() {
|
||||
self.deferred_sized_obligations.borrow_mut().push((ty, span, code));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_bound(
|
||||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
|
|
|
@ -35,11 +35,6 @@ pub struct Inherited<'a, 'tcx> {
|
|||
|
||||
pub(super) fulfillment_cx: RefCell<Box<dyn TraitEngine<'tcx>>>,
|
||||
|
||||
// Some additional `Sized` obligations badly affect type inference.
|
||||
// These obligations are added in a later stage of typeck.
|
||||
pub(super) deferred_sized_obligations:
|
||||
RefCell<Vec<(Ty<'tcx>, Span, traits::ObligationCauseCode<'tcx>)>>,
|
||||
|
||||
// When we process a call like `c()` where `c` is a closure type,
|
||||
// we may not have decided yet whether `c` is a `Fn`, `FnMut`, or
|
||||
// `FnOnce` closure. In that case, we defer full resolution of the
|
||||
|
@ -117,7 +112,6 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> {
|
|||
infcx,
|
||||
fulfillment_cx: RefCell::new(<dyn TraitEngine<'_>>::new(tcx)),
|
||||
locals: RefCell::new(Default::default()),
|
||||
deferred_sized_obligations: RefCell::new(Vec::new()),
|
||||
deferred_call_resolutions: RefCell::new(Default::default()),
|
||||
deferred_cast_checks: RefCell::new(Vec::new()),
|
||||
deferred_transmute_checks: RefCell::new(Vec::new()),
|
||||
|
|
|
@ -467,11 +467,6 @@ fn typeck_with_fallback<'tcx>(
|
|||
fcx.resolve_rvalue_scopes(def_id.to_def_id());
|
||||
fcx.resolve_generator_interiors(def_id.to_def_id());
|
||||
|
||||
for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) {
|
||||
let ty = fcx.normalize_ty(span, ty);
|
||||
fcx.require_type_is_sized(ty, span, code);
|
||||
}
|
||||
|
||||
fcx.select_all_obligations_or_error();
|
||||
|
||||
if !fcx.infcx.is_tainted_by_errors() {
|
||||
|
|
|
@ -394,7 +394,7 @@ impl f32 {
|
|||
|
||||
/// Not a Number (NaN).
|
||||
///
|
||||
/// Note that IEEE-745 doesn't define just a single NaN value;
|
||||
/// Note that IEEE-754 doesn't define just a single NaN value;
|
||||
/// a plethora of bit patterns are considered to be NaN.
|
||||
/// Furthermore, the standard makes a difference
|
||||
/// between a "signaling" and a "quiet" NaN,
|
||||
|
@ -632,7 +632,7 @@ impl f32 {
|
|||
}
|
||||
|
||||
/// Returns `true` if `self` has a positive sign, including `+0.0`, NaNs with
|
||||
/// positive sign bit and positive infinity. Note that IEEE-745 doesn't assign any
|
||||
/// positive sign bit and positive infinity. Note that IEEE-754 doesn't assign any
|
||||
/// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that
|
||||
/// the bit pattern of NaNs are conserved over arithmetic operations, the result of
|
||||
/// `is_sign_positive` on a NaN might produce an unexpected result in some cases.
|
||||
|
@ -654,7 +654,7 @@ impl f32 {
|
|||
}
|
||||
|
||||
/// Returns `true` if `self` has a negative sign, including `-0.0`, NaNs with
|
||||
/// negative sign bit and negative infinity. Note that IEEE-745 doesn't assign any
|
||||
/// negative sign bit and negative infinity. Note that IEEE-754 doesn't assign any
|
||||
/// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that
|
||||
/// the bit pattern of NaNs are conserved over arithmetic operations, the result of
|
||||
/// `is_sign_negative` on a NaN might produce an unexpected result in some cases.
|
||||
|
|
|
@ -393,7 +393,7 @@ impl f64 {
|
|||
|
||||
/// Not a Number (NaN).
|
||||
///
|
||||
/// Note that IEEE-745 doesn't define just a single NaN value;
|
||||
/// Note that IEEE-754 doesn't define just a single NaN value;
|
||||
/// a plethora of bit patterns are considered to be NaN.
|
||||
/// Furthermore, the standard makes a difference
|
||||
/// between a "signaling" and a "quiet" NaN,
|
||||
|
@ -624,7 +624,7 @@ impl f64 {
|
|||
}
|
||||
|
||||
/// Returns `true` if `self` has a positive sign, including `+0.0`, NaNs with
|
||||
/// positive sign bit and positive infinity. Note that IEEE-745 doesn't assign any
|
||||
/// positive sign bit and positive infinity. Note that IEEE-754 doesn't assign any
|
||||
/// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that
|
||||
/// the bit pattern of NaNs are conserved over arithmetic operations, the result of
|
||||
/// `is_sign_positive` on a NaN might produce an unexpected result in some cases.
|
||||
|
@ -655,7 +655,7 @@ impl f64 {
|
|||
}
|
||||
|
||||
/// Returns `true` if `self` has a negative sign, including `-0.0`, NaNs with
|
||||
/// negative sign bit and negative infinity. Note that IEEE-745 doesn't assign any
|
||||
/// negative sign bit and negative infinity. Note that IEEE-754 doesn't assign any
|
||||
/// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that
|
||||
/// the bit pattern of NaNs are conserved over arithmetic operations, the result of
|
||||
/// `is_sign_negative` on a NaN might produce an unexpected result in some cases.
|
||||
|
|
|
@ -2,8 +2,14 @@ use std::env;
|
|||
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
let target = env::var("TARGET").expect("TARGET was not set");
|
||||
println!("cargo:rerun-if-env-changed=CARGO_CFG_MIRI");
|
||||
|
||||
if env::var_os("CARGO_CFG_MIRI").is_some() {
|
||||
// Miri doesn't need the linker flags or a libunwind build.
|
||||
return;
|
||||
}
|
||||
|
||||
let target = env::var("TARGET").expect("TARGET was not set");
|
||||
if target.contains("android") {
|
||||
let build = cc::Build::new();
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 36383b4da21dbd0a0781473bc8ad7ef0ed1b6751
|
||||
Subproject commit 42ca0ef484fcc8437a0682cee23abe4b7c407d52
|
|
@ -1 +1 @@
|
|||
Subproject commit c55611dd6c58bdeb52423b5c52fd0f3c93615ba8
|
||||
Subproject commit 6038be9d37d7251c966b486154af621d1794d7af
|
|
@ -1 +1 @@
|
|||
Subproject commit 8d1e4dccf71114ff56f328f671f2026d8e6b62a2
|
||||
Subproject commit 8e6aa3448515a0654e347b5e2510f1d4bc4d5a64
|
|
@ -1 +1 @@
|
|||
Subproject commit f3d3953bf3b158d596c96d55ce5366f9f3f972e9
|
||||
Subproject commit e647eb102890e8927f488bea12672b079eff8d9d
|
|
@ -1 +1 @@
|
|||
Subproject commit ee342dc91e1ba1bb1e1f1318f84bbe3bfac04798
|
||||
Subproject commit 03301f8ae55fa6f20f7ea152a517598e6db2cdb7
|
|
@ -1 +1 @@
|
|||
Subproject commit 04f3cf0bb2f5a6ee2bfc4b1a6a6cd8c11d1c5531
|
||||
Subproject commit d3daa1f28e169087becbc5e2b49ac91ca0405a44
|
|
@ -1,7 +1,8 @@
|
|||
//! Validates syntax inside Rust code blocks (\`\`\`rust).
|
||||
use rustc_data_structures::sync::{Lock, Lrc};
|
||||
use rustc_errors::{
|
||||
emitter::Emitter, Applicability, Diagnostic, Handler, LazyFallbackBundle, LintDiagnosticBuilder,
|
||||
emitter::Emitter, translation::Translate, Applicability, Diagnostic, Handler,
|
||||
LazyFallbackBundle, LintDiagnosticBuilder,
|
||||
};
|
||||
use rustc_parse::parse_stream_from_source_str;
|
||||
use rustc_session::parse::ParseSess;
|
||||
|
@ -181,6 +182,16 @@ struct BufferEmitter {
|
|||
fallback_bundle: LazyFallbackBundle,
|
||||
}
|
||||
|
||||
impl Translate for BufferEmitter {
|
||||
fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
|
||||
&**self.fallback_bundle
|
||||
}
|
||||
}
|
||||
|
||||
impl Emitter for BufferEmitter {
|
||||
fn emit_diagnostic(&mut self, diag: &Diagnostic) {
|
||||
let mut buffer = self.buffer.borrow_mut();
|
||||
|
@ -194,12 +205,4 @@ impl Emitter for BufferEmitter {
|
|||
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
|
||||
&**self.fallback_bundle
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ where
|
|||
use std::convert::TryFrom;
|
||||
<[T; N.get()]>::try_from(())
|
||||
//~^ error: the trait bound
|
||||
//~| error: the trait bound
|
||||
//~| error: mismatched types
|
||||
}
|
||||
|
||||
|
|
|
@ -4,27 +4,28 @@
|
|||
// @is nested.json "$.crate_version" \"1.0.0\"
|
||||
// @is - "$.index[*][?(@.name=='nested')].kind" \"module\"
|
||||
// @is - "$.index[*][?(@.name=='nested')].inner.is_crate" true
|
||||
// @count - "$.index[*][?(@.name=='nested')].inner.items[*]" 1
|
||||
|
||||
// @set l1_id = - "$.index[*][?(@.name=='l1')].id"
|
||||
// @ismany - "$.index[*][?(@.name=='nested')].inner.items[*]" $l1_id
|
||||
|
||||
// @is nested.json "$.index[*][?(@.name=='l1')].kind" \"module\"
|
||||
// @is - "$.index[*][?(@.name=='l1')].inner.is_crate" false
|
||||
// @count - "$.index[*][?(@.name=='l1')].inner.items[*]" 2
|
||||
pub mod l1 {
|
||||
|
||||
// @is nested.json "$.index[*][?(@.name=='l3')].kind" \"module\"
|
||||
// @is - "$.index[*][?(@.name=='l3')].inner.is_crate" false
|
||||
// @count - "$.index[*][?(@.name=='l3')].inner.items[*]" 1
|
||||
// @set l3_id = - "$.index[*][?(@.name=='l3')].id"
|
||||
// @has - "$.index[*][?(@.name=='l1')].inner.items[*]" $l3_id
|
||||
pub mod l3 {
|
||||
|
||||
// @is nested.json "$.index[*][?(@.name=='L4')].kind" \"struct\"
|
||||
// @is - "$.index[*][?(@.name=='L4')].inner.struct_type" \"unit\"
|
||||
// @set l4_id = - "$.index[*][?(@.name=='L4')].id"
|
||||
// @has - "$.index[*][?(@.name=='l3')].inner.items[*]" $l4_id
|
||||
// @ismany - "$.index[*][?(@.name=='l3')].inner.items[*]" $l4_id
|
||||
pub struct L4;
|
||||
}
|
||||
// @is nested.json "$.index[*][?(@.inner.source=='l3::L4')].kind" \"import\"
|
||||
// @is - "$.index[*][?(@.inner.source=='l3::L4')].inner.glob" false
|
||||
// @is - "$.index[*][?(@.inner.source=='l3::L4')].inner.id" $l4_id
|
||||
// @set l4_use_id = - "$.index[*][?(@.inner.source=='l3::L4')].id"
|
||||
pub use l3::L4;
|
||||
}
|
||||
// @ismany - "$.index[*][?(@.name=='l1')].inner.items[*]" $l3_id $l4_use_id
|
||||
|
|
|
@ -4,15 +4,20 @@
|
|||
#![feature(no_core)]
|
||||
|
||||
// @is glob_extern.json "$.index[*][?(@.name=='mod1')].kind" \"module\"
|
||||
// @is glob_extern.json "$.index[*][?(@.name=='mod1')].inner.is_stripped" "true"
|
||||
// @is - "$.index[*][?(@.name=='mod1')].inner.is_stripped" "true"
|
||||
mod mod1 {
|
||||
extern "C" {
|
||||
// @has - "$.index[*][?(@.name=='public_fn')].id"
|
||||
// @set public_fn_id = - "$.index[*][?(@.name=='public_fn')].id"
|
||||
pub fn public_fn();
|
||||
// @!has - "$.index[*][?(@.name=='private_fn')]"
|
||||
fn private_fn();
|
||||
}
|
||||
// @ismany - "$.index[*][?(@.name=='mod1')].inner.items[*]" $public_fn_id
|
||||
// @set mod1_id = - "$.index[*][?(@.name=='mod1')].id"
|
||||
}
|
||||
|
||||
// @is - "$.index[*][?(@.kind=='import')].inner.glob" true
|
||||
// @is - "$.index[*][?(@.kind=='import')].inner.id" $mod1_id
|
||||
// @set use_id = - "$.index[*][?(@.kind=='import')].id"
|
||||
// @ismany - "$.index[*][?(@.name=='glob_extern')].inner.items[*]" $use_id
|
||||
pub use mod1::*;
|
||||
|
|
|
@ -16,7 +16,7 @@ mod mod1 {
|
|||
struct Mod2Private;
|
||||
}
|
||||
|
||||
// @has - "$.index[*][?(@.kind=='import' && @.inner.name=='mod2')]"
|
||||
// @set mod2_use_id = - "$.index[*][?(@.kind=='import' && @.inner.name=='mod2')].id"
|
||||
pub use self::mod2::*;
|
||||
|
||||
// @set m1pub_id = - "$.index[*][?(@.name=='Mod1Public')].id"
|
||||
|
@ -25,8 +25,9 @@ mod mod1 {
|
|||
struct Mod1Private;
|
||||
}
|
||||
|
||||
// @has - "$.index[*][?(@.kind=='import' && @.inner.name=='mod1')]"
|
||||
// @set mod1_use_id = - "$.index[*][?(@.kind=='import' && @.inner.name=='mod1')].id"
|
||||
pub use mod1::*;
|
||||
|
||||
// @has - "$.index[*][?(@.name=='mod2')].inner.items[*]" $m2pub_id
|
||||
// @has - "$.index[*][?(@.name=='mod1')].inner.items[*]" $m1pub_id
|
||||
// @ismany - "$.index[*][?(@.name=='mod2')].inner.items[*]" $m2pub_id
|
||||
// @ismany - "$.index[*][?(@.name=='mod1')].inner.items[*]" $m1pub_id $mod2_use_id
|
||||
// @ismany - "$.index[*][?(@.name=='glob_private')].inner.items[*]" $mod1_use_id
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
pub mod foo {
|
||||
// @set bar_id = in_root_and_mod_pub.json "$.index[*][?(@.name=='Bar')].id"
|
||||
// @has - "$.index[*][?(@.name=='foo')].inner.items[*]" $bar_id
|
||||
// @ismany - "$.index[*][?(@.name=='foo')].inner.items[*]" $bar_id
|
||||
pub struct Bar;
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,6 @@ pub use foo::Bar;
|
|||
pub mod baz {
|
||||
// @set baz_import_id = - "$.index[*][?(@.inner.source=='crate::foo::Bar')].id"
|
||||
// @is - "$.index[*][?(@.inner.source=='crate::foo::Bar')].inner.id" $bar_id
|
||||
// @has - "$.index[*][?(@.name=='baz')].inner.items[*]" $baz_import_id
|
||||
// @ismany - "$.index[*][?(@.name=='baz')].inner.items[*]" $baz_import_id
|
||||
pub use crate::foo::Bar;
|
||||
}
|
||||
|
|
|
@ -3,15 +3,13 @@
|
|||
#![no_core]
|
||||
#![feature(no_core)]
|
||||
|
||||
// @count macro.json "$.index[*][?(@.name=='macro')].inner.items[*]" 2
|
||||
|
||||
// @set repro_id = macro.json "$.index[*][?(@.name=='repro')].id"
|
||||
// @has - "$.index[*][?(@.name=='macro')].inner.items[*]" $repro_id
|
||||
#[macro_export]
|
||||
macro_rules! repro {
|
||||
() => {};
|
||||
}
|
||||
|
||||
// @set repro2_id = macro.json "$.index[*][?(@.inner.name=='repro2')].id"
|
||||
// @has - "$.index[*][?(@.name=='macro')].inner.items[*]" $repro2_id
|
||||
pub use crate::repro as repro2;
|
||||
|
||||
// @ismany macro.json "$.index[*][?(@.name=='macro')].inner.items[*]" $repro_id $repro2_id
|
||||
|
|
|
@ -1,18 +1,28 @@
|
|||
// aux-build:pub-struct.rs
|
||||
// ignore-tidy-linelength
|
||||
|
||||
// Test for the ICE in rust/83057
|
||||
// Am external type re-exported with different attributes shouldn't cause an error
|
||||
// Test for the ICE in https://github.com/rust-lang/rust/issues/83057
|
||||
// An external type re-exported with different attributes shouldn't cause an error
|
||||
|
||||
#![no_core]
|
||||
#![feature(no_core)]
|
||||
|
||||
extern crate pub_struct as foo;
|
||||
|
||||
#[doc(inline)]
|
||||
|
||||
// @set crate_use_id = private_twice_one_inline.json "$.index[*][?(@.docs=='Hack A')].id"
|
||||
// @set foo_id = - "$.index[*][?(@.docs=='Hack A')].inner.id"
|
||||
/// Hack A
|
||||
pub use foo::Foo;
|
||||
|
||||
// @set bar_id = - "$.index[*][?(@.name=='bar')].id"
|
||||
pub mod bar {
|
||||
// @is - "$.index[*][?(@.docs=='Hack B')].inner.id" $foo_id
|
||||
// @set bar_use_id = - "$.index[*][?(@.docs=='Hack B')].id"
|
||||
// @ismany - "$.index[*][?(@.name=='bar')].inner.items[*]" $bar_use_id
|
||||
/// Hack B
|
||||
pub use foo::Foo;
|
||||
}
|
||||
|
||||
// @count private_twice_one_inline.json "$.index[*][?(@.kind=='import')]" 2
|
||||
// @ismany - "$.index[*][?(@.kind=='import')].id" $crate_use_id $bar_use_id
|
||||
// @ismany - "$.index[*][?(@.name=='private_twice_one_inline')].inner.items[*]" $bar_id $crate_use_id
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// Test for the ICE in rust/83720
|
||||
// ignore-tidy-linelength
|
||||
|
||||
// Test for the ICE in https://github.com/rust-lang/rust/issues/83720
|
||||
// A pub-in-private type re-exported under two different names shouldn't cause an error
|
||||
|
||||
#![no_core]
|
||||
|
@ -7,11 +9,15 @@
|
|||
// @is private_two_names.json "$.index[*][?(@.name=='style')].kind" \"module\"
|
||||
// @is private_two_names.json "$.index[*][?(@.name=='style')].inner.is_stripped" "true"
|
||||
mod style {
|
||||
// @has - "$.index[*](?(@.name=='Color'))"
|
||||
// @set color_struct_id = - "$.index[*][?(@.kind=='struct' && @.name=='Color')].id"
|
||||
pub struct Color;
|
||||
}
|
||||
|
||||
// @has - "$.index[*][?(@.kind=='import' && @.inner.name=='Color')]"
|
||||
// @is - "$.index[*][?(@.kind=='import' && @.inner.name=='Color')].inner.id" $color_struct_id
|
||||
// @set color_export_id = - "$.index[*][?(@.kind=='import' && @.inner.name=='Color')].id"
|
||||
pub use style::Color;
|
||||
// @has - "$.index[*][?(@.kind=='import' && @.inner.name=='Colour')]"
|
||||
// @is - "$.index[*][?(@.kind=='import' && @.inner.name=='Colour')].inner.id" $color_struct_id
|
||||
// @set colour_export_id = - "$.index[*][?(@.kind=='import' && @.inner.name=='Colour')].id"
|
||||
pub use style::Color as Colour;
|
||||
|
||||
// @ismany - "$.index[*][?(@.name=='private_two_names')].inner.items[*]" $color_export_id $colour_export_id
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
#![feature(no_core)]
|
||||
|
||||
// @set inner_id = rename_public.json "$.index[*][?(@.name=='inner')].id"
|
||||
// @has - "$.index[*][?(@.name=='rename_public')].inner.items[*]" $inner_id
|
||||
pub mod inner {
|
||||
// @set public_id = - "$.index[*][?(@.name=='Public')].id"
|
||||
// @has - "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id
|
||||
// @ismany - "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id
|
||||
pub struct Public;
|
||||
}
|
||||
// @set import_id = - "$.index[*][?(@.inner.name=='NewName')].id"
|
||||
// @!has - "$.index[*][?(@.inner.name=='Public')]"
|
||||
// @has - "$.index[*][?(@.name=='rename_public')].inner.items[*]" $import_id
|
||||
// @is - "$.index[*][?(@.inner.name=='NewName')].inner.source" \"inner::Public\"
|
||||
pub use inner::Public as NewName;
|
||||
|
||||
// @ismany - "$.index[*][?(@.name=='rename_public')].inner.items[*]" $inner_id $import_id
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// ignore-tidy-linelength
|
||||
|
||||
// Regression test for <https://github.com/rust-lang/rust/issues/97432>.
|
||||
|
||||
#![feature(no_core)]
|
||||
|
@ -5,11 +7,17 @@
|
|||
#![no_core]
|
||||
|
||||
// @has same_type_reexported_more_than_once.json
|
||||
// @has - "$.index[*][?(@.name=='Trait')]"
|
||||
pub use inner::Trait;
|
||||
// @has - "$.index[*].inner[?(@.name=='Reexport')].id"
|
||||
pub use inner::Trait as Reexport;
|
||||
|
||||
mod inner {
|
||||
// @set trait_id = - "$.index[*][?(@.name=='Trait')].id"
|
||||
pub trait Trait {}
|
||||
}
|
||||
|
||||
// @set export_id = - "$.index[*][?(@.inner.name=='Trait')].id"
|
||||
// @is - "$.index[*][?(@.inner.name=='Trait')].inner.id" $trait_id
|
||||
pub use inner::Trait;
|
||||
// @set reexport_id = - "$.index[*][?(@.inner.name=='Reexport')].id"
|
||||
// @is - "$.index[*][?(@.inner.name=='Reexport')].inner.id" $trait_id
|
||||
pub use inner::Trait as Reexport;
|
||||
|
||||
// @ismany - "$.index[*][?(@.name=='same_type_reexported_more_than_once')].inner.items[*]" $reexport_id $export_id
|
||||
|
|
|
@ -10,6 +10,8 @@ mod inner {
|
|||
}
|
||||
|
||||
// @is - "$.index[*][?(@.kind=='import')].inner.name" \"Public\"
|
||||
// @set use_id = - "$.index[*][?(@.kind=='import')].id"
|
||||
pub use inner::Public;
|
||||
|
||||
// @has - "$.index[*][?(@.name=='inner')].inner.items[*]" $pub_id
|
||||
// @ismany - "$.index[*][?(@.name=='inner')].inner.items[*]" $pub_id
|
||||
// @ismany - "$.index[*][?(@.name=='simple_private')].inner.items[*]" $use_id
|
||||
|
|
|
@ -4,15 +4,15 @@
|
|||
#![feature(no_core)]
|
||||
|
||||
// @set inner_id = simple_public.json "$.index[*][?(@.name=='inner')].id"
|
||||
// @has - "$.index[*][?(@.name=='simple_public')].inner.items[*]" $inner_id
|
||||
pub mod inner {
|
||||
|
||||
// @set public_id = - "$.index[*][?(@.name=='Public')].id"
|
||||
// @has - "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id
|
||||
// @ismany - "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id
|
||||
pub struct Public;
|
||||
}
|
||||
|
||||
// @set import_id = - "$.index[*][?(@.inner.name=='Public')].id"
|
||||
// @has - "$.index[*][?(@.name=='simple_public')].inner.items[*]" $import_id
|
||||
// @is - "$.index[*][?(@.inner.name=='Public')].inner.source" \"inner::Public\"
|
||||
pub use inner::Public;
|
||||
|
||||
// @ismany - "$.index[*][?(@.name=='simple_public')].inner.items[*]" $import_id $inner_id
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
// @is fn_lifetime.json "$.index[*][?(@.name=='GenericFn')].kind" \"typedef\"
|
||||
|
||||
// @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*]" 1
|
||||
// @is - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].name" \"\'a\"
|
||||
// @ismany - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].name" \"\'a\"
|
||||
// @has - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].kind.lifetime"
|
||||
// @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].kind.lifetime.outlives[*]" 0
|
||||
// @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.where_predicates[*]" 0
|
||||
|
|
|
@ -33,7 +33,9 @@ error[E0277]: the trait bound `u32: Foo` is not satisfied
|
|||
--> $DIR/associated-types-path-2.rs:29:14
|
||||
|
|
||||
LL | f1(2u32, 4u32);
|
||||
| ^^^^ the trait `Foo` is not implemented for `u32`
|
||||
| -- ^^^^ the trait `Foo` is not implemented for `u32`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `Foo` is implemented for `i32`
|
||||
|
||||
|
|
|
@ -15,11 +15,16 @@ error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known
|
|||
--> $DIR/feature-gate-unsized_fn_params.rs:24:9
|
||||
|
|
||||
LL | foo(*x);
|
||||
| ^^ doesn't have a size known at compile-time
|
||||
| --- ^^ doesn't have a size known at compile-time
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
|
||||
= note: all function arguments must have a statically known size
|
||||
= help: unsized fn params are gated as an unstable feature
|
||||
help: function arguments must have a statically known size, borrowed types always have a known size
|
||||
|
|
||||
LL | foo(&*x);
|
||||
| +
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
fn main() {
|
||||
let _ = Iterator::next(&mut ());
|
||||
//~^ ERROR `()` is not an iterator
|
||||
//~| ERROR `()` is not an iterator
|
||||
|
||||
for _ in false {}
|
||||
//~^ ERROR `bool` is not an iterator
|
||||
|
@ -17,7 +16,6 @@ pub fn other() {
|
|||
|
||||
let _ = Iterator::next(&mut ());
|
||||
//~^ ERROR `()` is not an iterator
|
||||
//~| ERROR `()` is not an iterator
|
||||
|
||||
let _ = Iterator::next(&mut ());
|
||||
//~^ ERROR `()` is not an iterator
|
||||
|
|
|
@ -9,7 +9,7 @@ LL | let _ = Iterator::next(&mut ());
|
|||
= help: the trait `Iterator` is not implemented for `()`
|
||||
|
||||
error[E0277]: `bool` is not an iterator
|
||||
--> $DIR/issue-28098.rs:6:14
|
||||
--> $DIR/issue-28098.rs:5:14
|
||||
|
|
||||
LL | for _ in false {}
|
||||
| ^^^^^ `bool` is not an iterator
|
||||
|
@ -18,7 +18,7 @@ LL | for _ in false {}
|
|||
= note: required because of the requirements on the impl of `IntoIterator` for `bool`
|
||||
|
||||
error[E0277]: `()` is not an iterator
|
||||
--> $DIR/issue-28098.rs:9:28
|
||||
--> $DIR/issue-28098.rs:8:28
|
||||
|
|
||||
LL | let _ = Iterator::next(&mut ());
|
||||
| -------------- ^^^^^^^ `()` is not an iterator
|
||||
|
@ -28,15 +28,7 @@ LL | let _ = Iterator::next(&mut ());
|
|||
= help: the trait `Iterator` is not implemented for `()`
|
||||
|
||||
error[E0277]: `()` is not an iterator
|
||||
--> $DIR/issue-28098.rs:2:13
|
||||
|
|
||||
LL | let _ = Iterator::next(&mut ());
|
||||
| ^^^^^^^^^^^^^^ `()` is not an iterator
|
||||
|
|
||||
= help: the trait `Iterator` is not implemented for `()`
|
||||
|
||||
error[E0277]: `()` is not an iterator
|
||||
--> $DIR/issue-28098.rs:18:28
|
||||
--> $DIR/issue-28098.rs:17:28
|
||||
|
|
||||
LL | let _ = Iterator::next(&mut ());
|
||||
| -------------- ^^^^^^^ `()` is not an iterator
|
||||
|
@ -46,7 +38,7 @@ LL | let _ = Iterator::next(&mut ());
|
|||
= help: the trait `Iterator` is not implemented for `()`
|
||||
|
||||
error[E0277]: `()` is not an iterator
|
||||
--> $DIR/issue-28098.rs:22:28
|
||||
--> $DIR/issue-28098.rs:20:28
|
||||
|
|
||||
LL | let _ = Iterator::next(&mut ());
|
||||
| -------------- ^^^^^^^ `()` is not an iterator
|
||||
|
@ -56,7 +48,7 @@ LL | let _ = Iterator::next(&mut ());
|
|||
= help: the trait `Iterator` is not implemented for `()`
|
||||
|
||||
error[E0277]: `bool` is not an iterator
|
||||
--> $DIR/issue-28098.rs:25:14
|
||||
--> $DIR/issue-28098.rs:23:14
|
||||
|
|
||||
LL | for _ in false {}
|
||||
| ^^^^^ `bool` is not an iterator
|
||||
|
@ -64,14 +56,6 @@ LL | for _ in false {}
|
|||
= help: the trait `Iterator` is not implemented for `bool`
|
||||
= note: required because of the requirements on the impl of `IntoIterator` for `bool`
|
||||
|
||||
error[E0277]: `()` is not an iterator
|
||||
--> $DIR/issue-28098.rs:18:13
|
||||
|
|
||||
LL | let _ = Iterator::next(&mut ());
|
||||
| ^^^^^^^^^^^^^^ `()` is not an iterator
|
||||
|
|
||||
= help: the trait `Iterator` is not implemented for `()`
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
|
@ -32,11 +32,8 @@ impl Index<Bar<usize>> for [i32] {
|
|||
fn main() {
|
||||
Index::index(&[] as &[i32], 2u32);
|
||||
//~^ ERROR E0277
|
||||
//~| ERROR E0277
|
||||
Index::index(&[] as &[i32], Foo(2u32));
|
||||
//~^ ERROR E0277
|
||||
//~| ERROR E0277
|
||||
Index::index(&[] as &[i32], Bar(2u32));
|
||||
//~^ ERROR E0277
|
||||
//~| ERROR E0277
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ LL | Index::index(&[] as &[i32], 2u32);
|
|||
<[i32] as Index<Foo<usize>>>
|
||||
|
||||
error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
|
||||
--> $DIR/multiple-impls.rs:36:18
|
||||
--> $DIR/multiple-impls.rs:35:18
|
||||
|
|
||||
LL | Index::index(&[] as &[i32], Foo(2u32));
|
||||
| ------------ ^^^^^^^^^^^^^ on impl for Foo
|
||||
|
@ -25,7 +25,7 @@ LL | Index::index(&[] as &[i32], Foo(2u32));
|
|||
<[i32] as Index<Foo<usize>>>
|
||||
|
||||
error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
|
||||
--> $DIR/multiple-impls.rs:39:18
|
||||
--> $DIR/multiple-impls.rs:37:18
|
||||
|
|
||||
LL | Index::index(&[] as &[i32], Bar(2u32));
|
||||
| ------------ ^^^^^^^^^^^^^ on impl for Bar
|
||||
|
@ -37,39 +37,6 @@ LL | Index::index(&[] as &[i32], Bar(2u32));
|
|||
<[i32] as Index<Bar<usize>>>
|
||||
<[i32] as Index<Foo<usize>>>
|
||||
|
||||
error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
|
||||
--> $DIR/multiple-impls.rs:33:5
|
||||
|
|
||||
LL | Index::index(&[] as &[i32], 2u32);
|
||||
| ^^^^^^^^^^^^ trait message
|
||||
|
|
||||
= help: the trait `Index<u32>` is not implemented for `[i32]`
|
||||
= help: the following other types implement trait `Index<Idx>`:
|
||||
<[i32] as Index<Bar<usize>>>
|
||||
<[i32] as Index<Foo<usize>>>
|
||||
|
||||
error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
|
||||
--> $DIR/multiple-impls.rs:36:5
|
||||
|
|
||||
LL | Index::index(&[] as &[i32], Foo(2u32));
|
||||
| ^^^^^^^^^^^^ on impl for Foo
|
||||
|
|
||||
= help: the trait `Index<Foo<u32>>` is not implemented for `[i32]`
|
||||
= help: the following other types implement trait `Index<Idx>`:
|
||||
<[i32] as Index<Bar<usize>>>
|
||||
<[i32] as Index<Foo<usize>>>
|
||||
|
||||
error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
|
||||
--> $DIR/multiple-impls.rs:39:5
|
||||
|
|
||||
LL | Index::index(&[] as &[i32], Bar(2u32));
|
||||
| ^^^^^^^^^^^^ on impl for Bar
|
||||
|
|
||||
= help: the trait `Index<Bar<u32>>` is not implemented for `[i32]`
|
||||
= help: the following other types implement trait `Index<Idx>`:
|
||||
<[i32] as Index<Bar<usize>>>
|
||||
<[i32] as Index<Foo<usize>>>
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
|
@ -21,5 +21,4 @@ impl Index<usize> for [i32] {
|
|||
fn main() {
|
||||
Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
|
||||
//~^ ERROR E0277
|
||||
//~| ERROR E0277
|
||||
}
|
||||
|
|
|
@ -9,15 +9,6 @@ LL | Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
|
|||
= help: the trait `Index<u32>` is not implemented for `[i32]`
|
||||
= help: the trait `Index<usize>` is implemented for `[i32]`
|
||||
|
||||
error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
|
||||
--> $DIR/on-impl.rs:22:5
|
||||
|
|
||||
LL | Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
|
||||
| ^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
|
||||
|
|
||||
= help: the trait `Index<u32>` is not implemented for `[i32]`
|
||||
= help: the trait `Index<usize>` is implemented for `[i32]`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
14
src/test/ui/suggestions/return-cycle-2.rs
Normal file
14
src/test/ui/suggestions/return-cycle-2.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
use std::marker::PhantomData;
|
||||
|
||||
struct Token<T>(PhantomData<T>);
|
||||
|
||||
impl<T> Token<T> {
|
||||
fn as_ref(_: i32, _: i32) -> _ {
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
|
||||
//~| NOTE not allowed in type signatures
|
||||
//~| HELP replace with the correct return type
|
||||
Token(PhantomData::<&T>)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
12
src/test/ui/suggestions/return-cycle-2.stderr
Normal file
12
src/test/ui/suggestions/return-cycle-2.stderr
Normal file
|
@ -0,0 +1,12 @@
|
|||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/return-cycle-2.rs:6:34
|
||||
|
|
||||
LL | fn as_ref(_: i32, _: i32) -> _ {
|
||||
| ^
|
||||
| |
|
||||
| not allowed in type signatures
|
||||
| help: replace with the correct return type: `Token<&'static T>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0121`.
|
14
src/test/ui/suggestions/return-cycle.rs
Normal file
14
src/test/ui/suggestions/return-cycle.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
use std::marker::PhantomData;
|
||||
|
||||
struct Token<T>(PhantomData<T>);
|
||||
|
||||
impl<T> Token<T> {
|
||||
fn new() -> _ {
|
||||
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
|
||||
//~| NOTE not allowed in type signatures
|
||||
//~| HELP replace with the correct return type
|
||||
Token(PhantomData::<()>)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
12
src/test/ui/suggestions/return-cycle.stderr
Normal file
12
src/test/ui/suggestions/return-cycle.stderr
Normal file
|
@ -0,0 +1,12 @@
|
|||
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
|
||||
--> $DIR/return-cycle.rs:6:17
|
||||
|
|
||||
LL | fn new() -> _ {
|
||||
| ^
|
||||
| |
|
||||
| not allowed in type signatures
|
||||
| help: replace with the correct return type: `Token<()>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0121`.
|
|
@ -2,11 +2,16 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation
|
|||
--> $DIR/issue-30355.rs:5:8
|
||||
|
|
||||
LL | &X(*Y)
|
||||
| ^^ doesn't have a size known at compile-time
|
||||
| - ^^ doesn't have a size known at compile-time
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `[u8]`
|
||||
= note: all function arguments must have a statically known size
|
||||
= help: unsized fn params are gated as an unstable feature
|
||||
help: function arguments must have a statically known size, borrowed types always have a known size
|
||||
|
|
||||
LL | &X(&*Y)
|
||||
| +
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit efd4ca3dc0b89929dc8c5f5c023d25978d76cb61
|
||||
Subproject commit 9809f8ff33c2b998919fd0432c626f0f7323697a
|
|
@ -57,10 +57,10 @@ impl EarlyLintPass for OctalEscapes {
|
|||
}
|
||||
|
||||
if let ExprKind::Lit(lit) = &expr.kind {
|
||||
if matches!(lit.token.kind, LitKind::Str) {
|
||||
check_lit(cx, &lit.token, lit.span, true);
|
||||
} else if matches!(lit.token.kind, LitKind::ByteStr) {
|
||||
check_lit(cx, &lit.token, lit.span, false);
|
||||
if matches!(lit.token_lit.kind, LitKind::Str) {
|
||||
check_lit(cx, &lit.token_lit, lit.span, true);
|
||||
} else if matches!(lit.token_lit.kind, LitKind::ByteStr) {
|
||||
check_lit(cx, &lit.token_lit, lit.span, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -589,12 +589,12 @@ impl Write {
|
|||
},
|
||||
};
|
||||
|
||||
let replacement: String = match lit.token.kind {
|
||||
let replacement: String = match lit.token_lit.kind {
|
||||
LitKind::StrRaw(_) | LitKind::ByteStrRaw(_) if matches!(fmtstr.style, StrStyle::Raw(_)) => {
|
||||
lit.token.symbol.as_str().replace('{', "{{").replace('}', "}}")
|
||||
lit.token_lit.symbol.as_str().replace('{', "{{").replace('}', "}}")
|
||||
},
|
||||
LitKind::Str | LitKind::ByteStr if matches!(fmtstr.style, StrStyle::Cooked) => {
|
||||
lit.token.symbol.as_str().replace('{', "{{").replace('}', "}}")
|
||||
lit.token_lit.symbol.as_str().replace('{', "{{").replace('}', "}}")
|
||||
},
|
||||
LitKind::StrRaw(_)
|
||||
| LitKind::Str
|
||||
|
@ -603,7 +603,7 @@ impl Write {
|
|||
| LitKind::Integer
|
||||
| LitKind::Float
|
||||
| LitKind::Err => continue,
|
||||
LitKind::Byte | LitKind::Char => match lit.token.symbol.as_str() {
|
||||
LitKind::Byte | LitKind::Char => match lit.token_lit.symbol.as_str() {
|
||||
"\"" if matches!(fmtstr.style, StrStyle::Cooked) => "\\\"",
|
||||
"\"" if matches!(fmtstr.style, StrStyle::Raw(0)) => continue,
|
||||
"\\\\" if matches!(fmtstr.style, StrStyle::Raw(_)) => "\\",
|
||||
|
@ -614,7 +614,7 @@ impl Write {
|
|||
x => x,
|
||||
}
|
||||
.into(),
|
||||
LitKind::Bool => lit.token.symbol.as_str().deref().into(),
|
||||
LitKind::Bool => lit.token_lit.symbol.as_str().deref().into(),
|
||||
};
|
||||
|
||||
if !fmt_spans.is_empty() {
|
||||
|
|
|
@ -50,6 +50,7 @@ pub enum CommandKind {
|
|||
Has,
|
||||
Count,
|
||||
Is,
|
||||
IsMany,
|
||||
Set,
|
||||
}
|
||||
|
||||
|
@ -57,6 +58,7 @@ impl CommandKind {
|
|||
fn validate(&self, args: &[String], command_num: usize, lineno: usize) -> bool {
|
||||
let count = match self {
|
||||
CommandKind::Has => (1..=3).contains(&args.len()),
|
||||
CommandKind::IsMany => args.len() >= 3,
|
||||
CommandKind::Count | CommandKind::Is => 3 == args.len(),
|
||||
CommandKind::Set => 4 == args.len(),
|
||||
};
|
||||
|
@ -89,6 +91,7 @@ impl fmt::Display for CommandKind {
|
|||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let text = match self {
|
||||
CommandKind::Has => "has",
|
||||
CommandKind::IsMany => "ismany",
|
||||
CommandKind::Count => "count",
|
||||
CommandKind::Is => "is",
|
||||
CommandKind::Set => "set",
|
||||
|
@ -137,6 +140,7 @@ fn get_commands(template: &str) -> Result<Vec<Command>, ()> {
|
|||
"has" => CommandKind::Has,
|
||||
"count" => CommandKind::Count,
|
||||
"is" => CommandKind::Is,
|
||||
"ismany" => CommandKind::IsMany,
|
||||
"set" => CommandKind::Set,
|
||||
_ => {
|
||||
print_err(&format!("Unrecognized command name `@{}`", cmd), lineno);
|
||||
|
@ -227,6 +231,44 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
|
|||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
CommandKind::IsMany => {
|
||||
// @ismany <path> <jsonpath> <value>...
|
||||
let (path, query, values) = if let [path, query, values @ ..] = &command.args[..] {
|
||||
(path, query, values)
|
||||
} else {
|
||||
unreachable!("Checked in CommandKind::validate")
|
||||
};
|
||||
let val = cache.get_value(path)?;
|
||||
let got_values = select(&val, &query).unwrap();
|
||||
assert!(!command.negated, "`@!ismany` is not supported");
|
||||
|
||||
// Serde json doesn't implement Ord or Hash for Value, so we must
|
||||
// use a Vec here. While in theory that makes setwize equality
|
||||
// O(n^2), in practice n will never be large enought to matter.
|
||||
let expected_values =
|
||||
values.iter().map(|v| string_to_value(v, cache)).collect::<Vec<_>>();
|
||||
if expected_values.len() != got_values.len() {
|
||||
return Err(CkError::FailedCheck(
|
||||
format!(
|
||||
"Expected {} values, but `{}` matched to {} values ({:?})",
|
||||
expected_values.len(),
|
||||
query,
|
||||
got_values.len(),
|
||||
got_values
|
||||
),
|
||||
command,
|
||||
));
|
||||
};
|
||||
for got_value in got_values {
|
||||
if !expected_values.iter().any(|exp| &**exp == got_value) {
|
||||
return Err(CkError::FailedCheck(
|
||||
format!("`{}` has match {:?}, which was not expected", query, got_value),
|
||||
command,
|
||||
));
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
CommandKind::Count => {
|
||||
// @count <path> <jsonpath> <count> = Check that the jsonpath matches exactly [count] times
|
||||
assert_eq!(command.args.len(), 3);
|
||||
|
|
|
@ -79,7 +79,7 @@ pub(crate) fn format_expr(
|
|||
if let Some(expr_rw) = rewrite_literal(context, l, shape) {
|
||||
Some(expr_rw)
|
||||
} else {
|
||||
if let LitKind::StrRaw(_) = l.token.kind {
|
||||
if let LitKind::StrRaw(_) = l.token_lit.kind {
|
||||
Some(context.snippet(l.span).trim().into())
|
||||
} else {
|
||||
None
|
||||
|
@ -1226,7 +1226,7 @@ fn rewrite_string_lit(context: &RewriteContext<'_>, span: Span, shape: Shape) ->
|
|||
|
||||
fn rewrite_int_lit(context: &RewriteContext<'_>, lit: &ast::Lit, shape: Shape) -> Option<String> {
|
||||
let span = lit.span;
|
||||
let symbol = lit.token.symbol.as_str();
|
||||
let symbol = lit.token_lit.symbol.as_str();
|
||||
|
||||
if let Some(symbol_stripped) = symbol.strip_prefix("0x") {
|
||||
let hex_lit = match context.config.hex_literal_case() {
|
||||
|
@ -1239,7 +1239,9 @@ fn rewrite_int_lit(context: &RewriteContext<'_>, lit: &ast::Lit, shape: Shape) -
|
|||
format!(
|
||||
"0x{}{}",
|
||||
hex_lit,
|
||||
lit.token.suffix.map_or(String::new(), |s| s.to_string())
|
||||
lit.token_lit
|
||||
.suffix
|
||||
.map_or(String::new(), |s| s.to_string())
|
||||
),
|
||||
context.config.max_width(),
|
||||
shape,
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
|
|||
|
||||
use rustc_data_structures::sync::{Lrc, Send};
|
||||
use rustc_errors::emitter::{Emitter, EmitterWriter};
|
||||
use rustc_errors::translation::Translate;
|
||||
use rustc_errors::{ColorConfig, Diagnostic, Handler, Level as DiagnosticLevel};
|
||||
use rustc_session::parse::ParseSess as RawParseSess;
|
||||
use rustc_span::{
|
||||
|
@ -28,17 +29,22 @@ pub(crate) struct ParseSess {
|
|||
/// Emitter which discards every error.
|
||||
struct SilentEmitter;
|
||||
|
||||
impl Translate for SilentEmitter {
|
||||
fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
|
||||
panic!("silent emitter attempted to translate a diagnostic");
|
||||
}
|
||||
}
|
||||
|
||||
impl Emitter for SilentEmitter {
|
||||
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn emit_diagnostic(&mut self, _db: &Diagnostic) {}
|
||||
fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
|
||||
None
|
||||
}
|
||||
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
|
||||
panic!("silent emitter attempted to translate a diagnostic");
|
||||
}
|
||||
}
|
||||
|
||||
fn silent_emitter() -> Box<dyn Emitter + Send> {
|
||||
|
@ -62,10 +68,21 @@ impl SilentOnIgnoredFilesEmitter {
|
|||
}
|
||||
}
|
||||
|
||||
impl Translate for SilentOnIgnoredFilesEmitter {
|
||||
fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
|
||||
self.emitter.fluent_bundle()
|
||||
}
|
||||
|
||||
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
|
||||
self.emitter.fallback_fluent_bundle()
|
||||
}
|
||||
}
|
||||
|
||||
impl Emitter for SilentOnIgnoredFilesEmitter {
|
||||
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn emit_diagnostic(&mut self, db: &Diagnostic) {
|
||||
if db.level() == DiagnosticLevel::Fatal {
|
||||
return self.handle_non_ignoreable_error(db);
|
||||
|
@ -88,14 +105,6 @@ impl Emitter for SilentOnIgnoredFilesEmitter {
|
|||
}
|
||||
self.handle_non_ignoreable_error(db);
|
||||
}
|
||||
|
||||
fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
|
||||
self.emitter.fluent_bundle()
|
||||
}
|
||||
|
||||
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
|
||||
self.emitter.fallback_fluent_bundle()
|
||||
}
|
||||
}
|
||||
|
||||
fn default_handler(
|
||||
|
@ -340,19 +349,24 @@ mod tests {
|
|||
num_emitted_errors: Lrc<AtomicU32>,
|
||||
}
|
||||
|
||||
impl Translate for TestEmitter {
|
||||
fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
|
||||
panic!("test emitter attempted to translate a diagnostic");
|
||||
}
|
||||
}
|
||||
|
||||
impl Emitter for TestEmitter {
|
||||
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn emit_diagnostic(&mut self, _db: &Diagnostic) {
|
||||
self.num_emitted_errors.fetch_add(1, Ordering::Release);
|
||||
}
|
||||
fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
|
||||
None
|
||||
}
|
||||
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
|
||||
panic!("test emitter attempted to translate a diagnostic");
|
||||
}
|
||||
}
|
||||
|
||||
fn build_diagnostic(level: DiagnosticLevel, span: Option<MultiSpan>) -> Diagnostic {
|
||||
|
|
|
@ -178,6 +178,13 @@ trigger_files = [
|
|||
"src/tools/bump-stage0",
|
||||
]
|
||||
|
||||
[autolabel."A-translation"]
|
||||
trigger_files = [
|
||||
"compiler/rustc_error_messages",
|
||||
"compiler/rustc_errors/src/translation.rs",
|
||||
"compiler/rustc_macros/src/diagnostics"
|
||||
]
|
||||
|
||||
[notify-zulip."I-prioritize"]
|
||||
zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
|
||||
topic = "#{number} {title}"
|
||||
|
@ -342,3 +349,15 @@ cc = ["@rust-lang/rustfmt"]
|
|||
[mentions."compiler/rustc_middle/src/mir/syntax.rs"]
|
||||
message = "This PR changes MIR"
|
||||
cc = ["@oli-obk", "@RalfJung", "@JakobDegen", "@davidtwco", "@celinval", "@vakaras"]
|
||||
|
||||
[mentions."compiler/rustc_error_messages"]
|
||||
message = "`rustc_error_messages` was changed"
|
||||
cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank"]
|
||||
|
||||
[mentions."compiler/rustc_errors/src/translation.rs"]
|
||||
message = "`rustc_errors::translation` was changed"
|
||||
cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank"]
|
||||
|
||||
[mentions."compiler/rustc_macros/src/diagnostics"]
|
||||
message = "`rustc_macros::diagnostics` was changed"
|
||||
cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank"]
|
||||
|
|
Loading…
Add table
Reference in a new issue