diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 002e6874466bb..8dec12db9ca2b 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -43,6 +43,7 @@ use crate::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; use crate::hir::def::{Namespace, Res, DefKind, PartialRes, PerNS}; use crate::hir::{GenericArg, ConstArg}; use crate::hir::ptr::P; +use crate::lint; use crate::lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES, ELIDED_LIFETIMES_IN_PATHS}; use crate::middle::cstore::CrateStore; @@ -184,6 +185,8 @@ pub trait Resolver { ) -> (ast::Path, Res); fn has_derives(&self, node_id: NodeId, derives: SpecialDerives) -> bool; + + fn lint_buffer(&mut self) -> &mut lint::LintBuffer; } type NtToTokenstream = fn(&Nonterminal, &ParseSess, Span) -> TokenStream; @@ -1857,7 +1860,7 @@ impl<'a> LoweringContext<'a> { GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args { ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data), ParenthesizedGenericArgs::Warn => { - self.sess.buffer_lint( + self.resolver.lint_buffer().buffer_lint( PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES, CRATE_NODE_ID, data.span, @@ -1953,7 +1956,7 @@ impl<'a> LoweringContext<'a> { } AnonymousLifetimeMode::PassThrough | AnonymousLifetimeMode::ReportError => { - self.sess.buffer_lint_with_diagnostic( + self.resolver.lint_buffer().buffer_lint_with_diagnostic( ELIDED_LIFETIMES_IN_PATHS, CRATE_NODE_ID, path_span, @@ -3346,7 +3349,7 @@ impl<'a> LoweringContext<'a> { } } - fn maybe_lint_bare_trait(&self, span: Span, id: NodeId, is_global: bool) { + fn maybe_lint_bare_trait(&mut self, span: Span, id: NodeId, is_global: bool) { // FIXME(davidtwco): This is a hack to detect macros which produce spans of the // call site which do not have a macro backtrace. See #61963. let is_macro_callsite = self.sess.source_map() @@ -3354,7 +3357,7 @@ impl<'a> LoweringContext<'a> { .map(|snippet| snippet.starts_with("#[")) .unwrap_or(true); if !is_macro_callsite { - self.sess.buffer_lint_with_diagnostic( + self.resolver.lint_buffer().buffer_lint_with_diagnostic( builtin::BARE_TRAIT_OBJECTS, id, span, diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 1cb53d754dcd3..eef1cee8db37a 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -34,7 +34,6 @@ use crate::util::common::time; use errors::DiagnosticBuilder; use std::slice; -use std::default::Default as StdDefault; use rustc_data_structures::sync::{self, ParallelIterator, join, par_iter}; use rustc_serialize::{Decoder, Decodable, Encoder, Encodable}; use syntax::ast; @@ -584,12 +583,13 @@ impl<'a> EarlyContext<'a> { lint_store: &'a LintStore, krate: &'a ast::Crate, buffered: LintBuffer, + warn_about_weird_lints: bool, ) -> EarlyContext<'a> { EarlyContext { sess, krate, lint_store, - builder: LintLevelSets::builder(sess, lint_store), + builder: LintLevelSets::builder(sess, warn_about_weird_lints, lint_store), buffered, } } @@ -1490,9 +1490,10 @@ fn early_lint_crate( krate: &ast::Crate, pass: T, buffered: LintBuffer, + warn_about_weird_lints: bool, ) -> LintBuffer { let mut cx = EarlyContextAndPass { - context: EarlyContext::new(sess, lint_store, krate, buffered), + context: EarlyContext::new(sess, lint_store, krate, buffered, warn_about_weird_lints), pass, }; @@ -1514,22 +1515,19 @@ pub fn check_ast_crate( lint_store: &LintStore, krate: &ast::Crate, pre_expansion: bool, + lint_buffer: Option, builtin_lints: T, ) { - let (mut passes, mut buffered): (Vec<_>, _) = if pre_expansion { - ( - lint_store.pre_expansion_passes.iter().map(|p| (p)()).collect(), - LintBuffer::default(), - ) + let mut passes: Vec<_> = if pre_expansion { + lint_store.pre_expansion_passes.iter().map(|p| (p)()).collect() } else { - ( - lint_store.early_passes.iter().map(|p| (p)()).collect(), - sess.buffered_lints.borrow_mut().take().unwrap(), - ) + lint_store.early_passes.iter().map(|p| (p)()).collect() }; + let mut buffered = lint_buffer.unwrap_or_default(); if !sess.opts.debugging_opts.no_interleave_lints { - buffered = early_lint_crate(sess, lint_store, krate, builtin_lints, buffered); + buffered = early_lint_crate(sess, lint_store, krate, builtin_lints, buffered, + pre_expansion); if !passes.is_empty() { buffered = early_lint_crate( @@ -1538,6 +1536,7 @@ pub fn check_ast_crate( krate, EarlyLintPassObjects { lints: &mut passes[..] }, buffered, + pre_expansion, ); } } else { @@ -1549,6 +1548,7 @@ pub fn check_ast_crate( krate, EarlyLintPassObjects { lints: slice::from_mut(pass) }, buffered, + pre_expansion, ) }); } diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 4c60492e470c2..e470dbdf3239b 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -44,8 +44,12 @@ impl LintLevelSets { return me } - pub fn builder<'a>(sess: &'a Session, store: &LintStore) -> LintLevelsBuilder<'a> { - LintLevelsBuilder::new(sess, LintLevelSets::new(sess, store)) + pub fn builder<'a>( + sess: &'a Session, + warn_about_weird_lints: bool, + store: &LintStore, + ) -> LintLevelsBuilder<'a> { + LintLevelsBuilder::new(sess, warn_about_weird_lints, LintLevelSets::new(sess, store)) } fn process_command_line(&mut self, sess: &Session, store: &LintStore) { @@ -160,14 +164,18 @@ pub struct BuilderPush { } impl<'a> LintLevelsBuilder<'a> { - pub fn new(sess: &'a Session, sets: LintLevelSets) -> LintLevelsBuilder<'a> { + pub fn new( + sess: &'a Session, + warn_about_weird_lints: bool, + sets: LintLevelSets, + ) -> LintLevelsBuilder<'a> { assert_eq!(sets.list.len(), 1); LintLevelsBuilder { sess, sets, cur: 0, id_to_set: Default::default(), - warn_about_weird_lints: sess.buffered_lints.borrow().is_some(), + warn_about_weird_lints, } } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 3c35bdae66e9d..30e96428db779 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -643,13 +643,29 @@ impl LintBuffer { } } - pub fn take(&mut self, id: ast::NodeId) -> Vec { + fn take(&mut self, id: ast::NodeId) -> Vec { self.map.remove(&id).unwrap_or_default() } - pub fn get_any(&self) -> Option<&[BufferedEarlyLint]> { - let key = self.map.keys().next().map(|k| *k); - key.map(|k| &self.map[&k][..]) + pub fn buffer_lint>( + &mut self, + lint: &'static Lint, + id: ast::NodeId, + sp: S, + msg: &str, + ) { + self.add_lint(lint, id, sp.into(), msg, BuiltinLintDiagnostics::Normal) + } + + pub fn buffer_lint_with_diagnostic>( + &mut self, + lint: &'static Lint, + id: ast::NodeId, + sp: S, + msg: &str, + diagnostic: BuiltinLintDiagnostics, + ) { + self.add_lint(lint, id, sp.into(), msg, diagnostic) } } @@ -779,7 +795,7 @@ fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> &LintLevelMap { assert_eq!(cnum, LOCAL_CRATE); let store = &tcx.lint_store; let mut builder = LintLevelMapBuilder { - levels: LintLevelSets::builder(tcx.sess, &store), + levels: LintLevelSets::builder(tcx.sess, false, &store), tcx: tcx, store: store, }; diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index e65f17c79497e..93d0627ac6e40 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -586,7 +586,7 @@ pub fn rustc_deprecation_message(depr: &RustcDeprecation, path: &str) -> (String } pub fn early_report_deprecation( - sess: &Session, + lint_buffer: &'a mut lint::LintBuffer, message: &str, suggestion: Option, lint: &'static Lint, @@ -597,7 +597,7 @@ pub fn early_report_deprecation( } let diag = BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span); - sess.buffer_lint_with_diagnostic(lint, CRATE_NODE_ID, span, message, diag); + lint_buffer.buffer_lint_with_diagnostic(lint, CRATE_NODE_ID, span, message, diag); } fn late_report_deprecation( diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index fdca6d0e17a1d..7cae74b59c7f9 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -191,7 +191,7 @@ rustc_queries! { /// Returns the inferred outlives predicates (e.g., for `struct /// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`). - query inferred_outlives_of(_: DefId) -> &'tcx [ty::Predicate<'tcx>] {} + query inferred_outlives_of(_: DefId) -> &'tcx [(ty::Predicate<'tcx>, Span)] {} /// Maps from the `DefId` of a trait to the list of /// super-predicates. This is a subset of the full list of diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 33b9ddaa62230..2bcddeaf1962d 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1469,7 +1469,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, (such as entering an empty infinite loop) by inserting llvm.sideeffect"), } -pub fn default_lib_output() -> CrateType { +pub const fn default_lib_output() -> CrateType { CrateType::Rlib } diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index bd2460cfab116..d4ddbe43c3612 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -6,7 +6,6 @@ use crate::hir::def_id::CrateNum; use rustc_data_structures::fingerprint::Fingerprint; use crate::lint; -use crate::lint::builtin::BuiltinLintDiagnostics; use crate::session::config::{OutputType, PrintRequest, Sanitizer, SwitchWithOptPath}; use crate::session::search_paths::{PathKind, SearchPath}; use crate::util::nodemap::{FxHashMap, FxHashSet}; @@ -77,13 +76,6 @@ pub struct Session { /// if the value stored here has been affected by path remapping. pub working_dir: (PathBuf, bool), - /// This is intended to be used from a single thread. - /// - /// FIXME: there was a previous comment about this not being thread safe, - /// but it's not clear how or why that's the case. The LintBuffer itself is certainly thread - /// safe at least from a "Rust safety" standpoint. - pub buffered_lints: Lock>, - /// Set of `(DiagnosticId, Option, message)` tuples tracking /// (sub)diagnostics that have been set once, but should not be set again, /// in order to avoid redundantly verbose output (Issue #24690, #44953). @@ -363,35 +355,6 @@ impl Session { self.diagnostic().span_note_without_error(sp, msg) } - pub fn buffer_lint>( - &self, - lint: &'static lint::Lint, - id: ast::NodeId, - sp: S, - msg: &str, - ) { - match *self.buffered_lints.borrow_mut() { - Some(ref mut buffer) => { - buffer.add_lint(lint, id, sp.into(), msg, BuiltinLintDiagnostics::Normal) - } - None => bug!("can't buffer lints after HIR lowering"), - } - } - - pub fn buffer_lint_with_diagnostic>( - &self, - lint: &'static lint::Lint, - id: ast::NodeId, - sp: S, - msg: &str, - diagnostic: BuiltinLintDiagnostics, - ) { - match *self.buffered_lints.borrow_mut() { - Some(ref mut buffer) => buffer.add_lint(lint, id, sp.into(), msg, diagnostic), - None => bug!("can't buffer lints after HIR lowering"), - } - } - pub fn reserve_node_ids(&self, count: usize) -> ast::NodeId { let id = self.next_node_id.get(); @@ -1215,7 +1178,6 @@ fn build_session_( sysroot, local_crate_source_file, working_dir, - buffered_lints: Lock::new(Some(Default::default())), one_time_diagnostics: Default::default(), plugin_llvm_passes: OneThread::new(RefCell::new(Vec::new())), plugin_attributes: Lock::new(Vec::new()), diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 4696d4da58ec0..2734fce4ea55a 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -378,15 +378,21 @@ fn orphan_check_trait_ref<'tcx>( // Let Ti be the first such type. // - No uncovered type parameters P1..=Pn may appear in T0..Ti (excluding Ti) // - fn uncover_fundamental_ty(ty: Ty<'_>) -> Vec> { - if fundamental_ty(ty) { - ty.walk_shallow().flat_map(|ty| uncover_fundamental_ty(ty)).collect() + fn uncover_fundamental_ty<'a>( + tcx: TyCtxt<'_>, + ty: Ty<'a>, + in_crate: InCrate, + ) -> Vec> { + if fundamental_ty(ty) && !ty_is_local(tcx, ty, in_crate) { + ty.walk_shallow().flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate)).collect() } else { vec![ty] } } - for input_ty in trait_ref.input_types().flat_map(uncover_fundamental_ty) { + for input_ty in + trait_ref.input_types().flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate)) + { debug!("orphan_check_trait_ref: check ty `{:?}`", input_ty); if ty_is_local(tcx, input_ty, in_crate) { debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty); diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index e684cdc0a3872..be9e24cb1a291 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -195,8 +195,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { obligation: &PredicateObligation<'tcx>, error: &MismatchedProjectionTypes<'tcx>, ) { - let predicate = - self.resolve_vars_if_possible(&obligation.predicate); + let predicate = self.resolve_vars_if_possible(&obligation.predicate); if predicate.references_error() { return @@ -228,7 +227,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { &mut obligations ); if let Err(error) = self.at(&obligation.cause, obligation.param_env) - .eq(normalized_ty, data.ty) { + .eq(normalized_ty, data.ty) + { values = Some(infer::ValuePairs::Types(ExpectedFound { expected: normalized_ty, found: data.ty, @@ -239,13 +239,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } let msg = format!("type mismatch resolving `{}`", predicate); - let error_id = (DiagnosticMessageId::ErrorId(271), - Some(obligation.cause.span), msg); + let error_id = ( + DiagnosticMessageId::ErrorId(271), + Some(obligation.cause.span), + msg, + ); let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id); if fresh { let mut diag = struct_span_err!( - self.tcx.sess, obligation.cause.span, E0271, - "type mismatch resolving `{}`", predicate + self.tcx.sess, + obligation.cause.span, + E0271, + "type mismatch resolving `{}`", + predicate ); self.note_type_err(&mut diag, &obligation.cause, None, values, err); self.note_obligation_cause(&mut diag, obligation); @@ -532,23 +538,33 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// whose result could not be truly determined and thus we can't say /// if the program type checks or not -- and they are unusual /// occurrences in any case. - pub fn report_overflow_error(&self, - obligation: &Obligation<'tcx, T>, - suggest_increasing_limit: bool) -> ! + pub fn report_overflow_error( + &self, + obligation: &Obligation<'tcx, T>, + suggest_increasing_limit: bool, + ) -> ! where T: fmt::Display + TypeFoldable<'tcx> { let predicate = self.resolve_vars_if_possible(&obligation.predicate); - let mut err = struct_span_err!(self.tcx.sess, obligation.cause.span, E0275, - "overflow evaluating the requirement `{}`", - predicate); + let mut err = struct_span_err!( + self.tcx.sess, + obligation.cause.span, + E0275, + "overflow evaluating the requirement `{}`", + predicate + ); if suggest_increasing_limit { self.suggest_new_overflow_limit(&mut err); } - self.note_obligation_cause_code(&mut err, &obligation.predicate, &obligation.cause.code, - &mut vec![]); + self.note_obligation_cause_code( + &mut err, + &obligation.predicate, + &obligation.cause.code, + &mut vec![], + ); err.emit(); self.tcx.sess.abort_if_errors(); @@ -2197,6 +2213,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ); } } + ObligationCauseCode::AssocTypeBound(impl_span, orig) => { + err.span_label(orig, "associated type defined here"); + if let Some(sp) = impl_span { + err.span_label(sp, "in this `impl` item"); + } + } } } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index eb4b114eb301c..1a1c021c3ea27 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -271,6 +271,8 @@ pub enum ObligationCauseCode<'tcx> { /// #[feature(trivial_bounds)] is not enabled TrivialBound, + + AssocTypeBound(/*impl*/ Option, /*original*/ Span), } // `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger. diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 18db3c8d10b7c..ca80bb66cb761 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -548,6 +548,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { super::MethodReceiver => Some(super::MethodReceiver), super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)), super::TrivialBound => Some(super::TrivialBound), + super::AssocTypeBound(impl_sp, sp) => Some(super::AssocTypeBound(impl_sp, sp)), } } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 4660e8025d48e..6022687811d52 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1138,7 +1138,7 @@ pub struct CratePredicatesMap<'tcx> { /// For each struct with outlive bounds, maps to a vector of the /// predicate of its outlive bounds. If an item has no outlives /// bounds, it will have no entry. - pub predicates: FxHashMap]>, + pub predicates: FxHashMap, Span)]>, } impl<'tcx> AsRef> for Predicate<'tcx> { @@ -3141,6 +3141,7 @@ impl<'tcx> TyCtxt<'tcx> { } } +#[derive(Clone)] pub struct AssocItemsIterator<'tcx> { tcx: TyCtxt<'tcx>, def_ids: &'tcx [DefId], diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index b50e819c956e0..4ea01bf96476a 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -22,11 +22,14 @@ pub fn obligations<'a, 'tcx>( ty: Ty<'tcx>, span: Span, ) -> Option>> { - let mut wf = WfPredicates { infcx, - param_env, - body_id, - span, - out: vec![] }; + let mut wf = WfPredicates { + infcx, + param_env, + body_id, + span, + out: vec![], + item: None, + }; if wf.compute(ty) { debug!("wf::obligations({:?}, body_id={:?}) = {:?}", ty, body_id, wf.out); let result = wf.normalize(); @@ -47,8 +50,9 @@ pub fn trait_obligations<'a, 'tcx>( body_id: hir::HirId, trait_ref: &ty::TraitRef<'tcx>, span: Span, + item: Option<&'tcx hir::Item>, ) -> Vec> { - let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![] }; + let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item }; wf.compute_trait_ref(trait_ref, Elaborate::All); wf.normalize() } @@ -60,7 +64,7 @@ pub fn predicate_obligations<'a, 'tcx>( predicate: &ty::Predicate<'tcx>, span: Span, ) -> Vec> { - let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![] }; + let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None }; // (*) ok to skip binders, because wf code is prepared for it match *predicate { @@ -107,6 +111,7 @@ struct WfPredicates<'a, 'tcx> { body_id: hir::HirId, span: Span, out: Vec>, + item: Option<&'tcx hir::Item>, } /// Controls whether we "elaborate" supertraits and so forth on the WF @@ -157,33 +162,162 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { .collect() } - /// Pushes the obligations required for `trait_ref` to be WF into - /// `self.out`. + /// Pushes the obligations required for `trait_ref` to be WF into `self.out`. fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elaborate) { + let tcx = self.infcx.tcx; let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.substs); let cause = self.cause(traits::MiscObligation); let param_env = self.param_env; + let item = &self.item; + let extend_cause_with_original_assoc_item_obligation = | + cause: &mut traits::ObligationCause<'_>, + pred: &ty::Predicate<'_>, + trait_assoc_items: ty::AssocItemsIterator<'_>, + | { + let item_span = item.map(|i| tcx.sess.source_map().def_span(i.span)); + match pred { + ty::Predicate::Projection(proj) => { + // The obligation comes not from the current `impl` nor the `trait` being + // implemented, but rather from a "second order" obligation, like in + // `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs`: + // + // error[E0271]: type mismatch resolving `::Ok == ()` + // --> $DIR/point-at-type-on-obligation-failure.rs:13:5 + // | + // LL | type Ok; + // | -- associated type defined here + // ... + // LL | impl Bar for Foo { + // | ---------------- in this `impl` item + // LL | type Ok = (); + // | ^^^^^^^^^^^^^ expected u32, found () + // | + // = note: expected type `u32` + // found type `()` + // + // FIXME: we would want to point a span to all places that contributed to this + // obligation. In the case above, it should be closer to: + // + // error[E0271]: type mismatch resolving `::Ok == ()` + // --> $DIR/point-at-type-on-obligation-failure.rs:13:5 + // | + // LL | type Ok; + // | -- associated type defined here + // LL | type Sibling: Bar2; + // | -------------------------------- obligation set here + // ... + // LL | impl Bar for Foo { + // | ---------------- in this `impl` item + // LL | type Ok = (); + // | ^^^^^^^^^^^^^ expected u32, found () + // ... + // LL | impl Bar2 for Foo2 { + // | ---------------- in this `impl` item + // LL | type Ok = u32; + // | -------------- obligation set here + // | + // = note: expected type `u32` + // found type `()` + if let Some(hir::ItemKind::Impl(.., impl_items)) = item.map(|i| &i.kind) { + let trait_assoc_item = tcx.associated_item(proj.projection_def_id()); + if let Some(impl_item) = impl_items.iter().filter(|item| { + item.ident == trait_assoc_item.ident + }).next() { + cause.span = impl_item.span; + cause.code = traits::AssocTypeBound( + item_span, + trait_assoc_item.ident.span, + ); + } + } + } + ty::Predicate::Trait(proj) => { + // An associated item obligation born out of the `trait` failed to be met. + // Point at the `impl` that failed the obligation, the associated item that + // needed to meet the obligation, and the definition of that associated item, + // which should hold the obligation in most cases. An example can be seen in + // `src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs`: + // + // error[E0277]: the trait bound `bool: Bar` is not satisfied + // --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5 + // | + // LL | type Assoc: Bar; + // | ----- associated type defined here + // ... + // LL | impl Foo for () { + // | --------------- in this `impl` item + // LL | type Assoc = bool; + // | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool` + // + // FIXME: if the obligation comes from the where clause in the `trait`, we + // should point at it: + // + // error[E0277]: the trait bound `bool: Bar` is not satisfied + // --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5 + // | + // | trait Foo where >::Assoc: Bar { + // | -------------------------- obligation set here + // LL | type Assoc; + // | ----- associated type defined here + // ... + // LL | impl Foo for () { + // | --------------- in this `impl` item + // LL | type Assoc = bool; + // | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool` + if let ( + ty::Projection(ty::ProjectionTy { item_def_id, .. }), + Some(hir::ItemKind::Impl(.., impl_items)), + ) = (&proj.skip_binder().self_ty().kind, item.map(|i| &i.kind)) { + if let Some((impl_item, trait_assoc_item)) = trait_assoc_items + .filter(|i| i.def_id == *item_def_id) + .next() + .and_then(|trait_assoc_item| impl_items.iter() + .filter(|i| i.ident == trait_assoc_item.ident) + .next() + .map(|impl_item| (impl_item, trait_assoc_item))) + { + cause.span = impl_item.span; + cause.code = traits::AssocTypeBound( + item_span, + trait_assoc_item.ident.span, + ); + } + } + } + _ => {} + } + }; + if let Elaborate::All = elaborate { + let trait_assoc_items = tcx.associated_items(trait_ref.def_id); + let predicates = obligations.iter() - .map(|obligation| obligation.predicate.clone()) - .collect(); - let implied_obligations = traits::elaborate_predicates(self.infcx.tcx, predicates); + .map(|obligation| obligation.predicate.clone()) + .collect(); + let implied_obligations = traits::elaborate_predicates(tcx, predicates); let implied_obligations = implied_obligations.map(|pred| { - traits::Obligation::new(cause.clone(), param_env, pred) + let mut cause = cause.clone(); + extend_cause_with_original_assoc_item_obligation( + &mut cause, + &pred, + trait_assoc_items.clone(), + ); + traits::Obligation::new(cause, param_env, pred) }); self.out.extend(implied_obligations); } self.out.extend(obligations); - self.out.extend( - trait_ref.substs.types() - .filter(|ty| !ty.has_escaping_bound_vars()) - .map(|ty| traits::Obligation::new(cause.clone(), - param_env, - ty::Predicate::WellFormed(ty)))); + self.out.extend(trait_ref.substs.types() + .filter(|ty| !ty.has_escaping_bound_vars()) + .map(|ty| traits::Obligation::new( + cause.clone(), + param_env, + ty::Predicate::WellFormed(ty), + ))); } /// Pushes the obligations required for `trait_ref::Item` to be WF diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 15adf7e4add73..6e8bc11162f66 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -106,8 +106,6 @@ pub fn abort_on_err(result: Result, sess: &Session) -> T { pub trait Callbacks { /// Called before creating the compiler instance fn config(&mut self, _config: &mut interface::Config) {} - /// Called early during compilation to allow other drivers to easily register lints. - fn extra_lints(&mut self, _ls: &mut lint::LintStore) {} /// Called after parsing. Return value instructs the compiler whether to /// continue the compilation afterwards (defaults to `Compilation::Continue`) fn after_parsing(&mut self, _compiler: &interface::Compiler) -> Compilation { diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 58936172c5bce..cb498285c1903 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -267,6 +267,7 @@ fn configure_and_expand_inner<'a>( lint_store, &krate, true, + None, rustc_lint::BuiltinCombinedPreExpansionLintPass::new()); }); @@ -293,6 +294,8 @@ fn configure_and_expand_inner<'a>( krate }); + util::check_attr_crate_type(&krate.attrs, &mut resolver.lint_buffer()); + syntax_ext::plugin_macro_defs::inject( &mut krate, &mut resolver, plugin_info.syntax_exts, sess.edition() ); @@ -366,7 +369,7 @@ fn configure_and_expand_inner<'a>( for span in missing_fragment_specifiers { let lint = lint::builtin::MISSING_FRAGMENT_SPECIFIER; let msg = "missing fragment specifier"; - sess.buffer_lint(lint, ast::CRATE_NODE_ID, span, msg); + resolver.lint_buffer().buffer_lint(lint, ast::CRATE_NODE_ID, span, msg); } if cfg!(windows) { env::set_var("PATH", &old_path); @@ -395,7 +398,7 @@ fn configure_and_expand_inner<'a>( } let has_proc_macro_decls = time(sess, "AST validation", || { - ast_validation::check_crate(sess, &krate) + ast_validation::check_crate(sess, &krate, &mut resolver.lint_buffer()) }); @@ -464,7 +467,7 @@ fn configure_and_expand_inner<'a>( info!("{} parse sess buffered_lints", buffered_lints.len()); for BufferedEarlyLint{id, span, msg, lint_id} in buffered_lints.drain(..) { let lint = lint::Lint::from_parser_lint_id(lint_id); - sess.buffer_lint(lint, id, span, &msg); + resolver.lint_buffer().buffer_lint(lint, id, span, &msg); } }); @@ -496,6 +499,7 @@ pub fn lower_to_hir( lint_store, &krate, false, + Some(std::mem::take(resolver.lint_buffer())), rustc_lint::BuiltinCombinedEarlyLintPass::new(), ) }); diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 8f11dc9372728..d0c15073f1640 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -526,6 +526,63 @@ pub(crate) fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguat CrateDisambiguator::from(hasher.finish::()) } +pub(crate) fn check_attr_crate_type(attrs: &[ast::Attribute], lint_buffer: &mut lint::LintBuffer) { + // Unconditionally collect crate types from attributes to make them used + for a in attrs.iter() { + if a.check_name(sym::crate_type) { + if let Some(n) = a.value_str() { + if let Some(_) = categorize_crate_type(n) { + return; + } + + if let ast::MetaItemKind::NameValue(spanned) = a.meta().unwrap().kind { + let span = spanned.span; + let lev_candidate = find_best_match_for_name( + CRATE_TYPES.iter().map(|(k, _)| k), + &n.as_str(), + None + ); + if let Some(candidate) = lev_candidate { + lint_buffer.buffer_lint_with_diagnostic( + lint::builtin::UNKNOWN_CRATE_TYPES, + ast::CRATE_NODE_ID, + span, + "invalid `crate_type` value", + lint::builtin::BuiltinLintDiagnostics:: + UnknownCrateTypes( + span, + "did you mean".to_string(), + format!("\"{}\"", candidate) + ) + ); + } else { + lint_buffer.buffer_lint( + lint::builtin::UNKNOWN_CRATE_TYPES, + ast::CRATE_NODE_ID, + span, + "invalid `crate_type` value" + ); + } + } + } + } + } +} + +const CRATE_TYPES: &[(Symbol, config::CrateType)] = &[ + (sym::rlib, config::CrateType::Rlib), + (sym::dylib, config::CrateType::Dylib), + (sym::cdylib, config::CrateType::Cdylib), + (sym::lib, config::default_lib_output()), + (sym::staticlib, config::CrateType::Staticlib), + (sym::proc_dash_macro, config::CrateType::ProcMacro), + (sym::bin, config::CrateType::Executable), +]; + +fn categorize_crate_type(s: Symbol) -> Option { + Some(CRATE_TYPES.iter().find(|(key, _)| *key == s)?.1) +} + pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec { // Unconditionally collect crate types from attributes to make them used let attr_types: Vec = attrs @@ -533,56 +590,8 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec Some(config::CrateType::Rlib), - Some(sym::dylib) => Some(config::CrateType::Dylib), - Some(sym::cdylib) => Some(config::CrateType::Cdylib), - Some(sym::lib) => Some(config::default_lib_output()), - Some(sym::staticlib) => Some(config::CrateType::Staticlib), - Some(sym::proc_dash_macro) => Some(config::CrateType::ProcMacro), - Some(sym::bin) => Some(config::CrateType::Executable), - Some(n) => { - let crate_types = vec![ - sym::rlib, - sym::dylib, - sym::cdylib, - sym::lib, - sym::staticlib, - sym::proc_dash_macro, - sym::bin - ]; - - if let ast::MetaItemKind::NameValue(spanned) = a.meta().unwrap().kind { - let span = spanned.span; - let lev_candidate = find_best_match_for_name( - crate_types.iter(), - &n.as_str(), - None - ); - if let Some(candidate) = lev_candidate { - session.buffer_lint_with_diagnostic( - lint::builtin::UNKNOWN_CRATE_TYPES, - ast::CRATE_NODE_ID, - span, - "invalid `crate_type` value", - lint::builtin::BuiltinLintDiagnostics:: - UnknownCrateTypes( - span, - "did you mean".to_string(), - format!("\"{}\"", candidate) - ) - ); - } else { - session.buffer_lint( - lint::builtin::UNKNOWN_CRATE_TYPES, - ast::CRATE_NODE_ID, - span, - "invalid `crate_type` value" - ); - } - } - None - } - None => None + Some(s) => categorize_crate_type(s), + _ => None, } } else { None diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index ad674911e6f33..7c19449f96b86 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1497,10 +1497,10 @@ declare_lint_pass!(ExplicitOutlivesRequirements => [EXPLICIT_OUTLIVES_REQUIREMEN impl ExplicitOutlivesRequirements { fn lifetimes_outliving_lifetime<'tcx>( - inferred_outlives: &'tcx [ty::Predicate<'tcx>], + inferred_outlives: &'tcx [(ty::Predicate<'tcx>, Span)], index: u32, ) -> Vec> { - inferred_outlives.iter().filter_map(|pred| { + inferred_outlives.iter().filter_map(|(pred, _)| { match pred { ty::Predicate::RegionOutlives(outlives) => { let outlives = outlives.skip_binder(); @@ -1517,10 +1517,10 @@ impl ExplicitOutlivesRequirements { } fn lifetimes_outliving_type<'tcx>( - inferred_outlives: &'tcx [ty::Predicate<'tcx>], + inferred_outlives: &'tcx [(ty::Predicate<'tcx>, Span)], index: u32, ) -> Vec> { - inferred_outlives.iter().filter_map(|pred| { + inferred_outlives.iter().filter_map(|(pred, _)| { match pred { ty::Predicate::TypeOutlives(outlives) => { let outlives = outlives.skip_binder(); @@ -1539,7 +1539,7 @@ impl ExplicitOutlivesRequirements { &self, param: &'tcx hir::GenericParam, tcx: TyCtxt<'tcx>, - inferred_outlives: &'tcx [ty::Predicate<'tcx>], + inferred_outlives: &'tcx [(ty::Predicate<'tcx>, Span)], ty_generics: &'tcx ty::Generics, ) -> Vec> { let index = ty_generics.param_def_id_to_index[ diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 0dc9f91ae00e1..08554c83ed5bf 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -197,6 +197,13 @@ impl<'tcx> SpecializedEncoder for EncodeContext<'tcx> { return TAG_INVALID_SPAN.encode(self) } + // HACK(eddyb) there's no way to indicate which crate a Span is coming + // from right now, so decoding would fail to find the SourceFile if + // it's not local to the crate the Span is found in. + if self.source_file_cache.is_imported() { + return TAG_INVALID_SPAN.encode(self) + } + TAG_VALID_SPAN.encode(self)?; span.lo.encode(self)?; @@ -379,6 +386,7 @@ impl<'tcx> EncodeContext<'tcx> { .filter(|source_file| { // No need to re-export imported source_files, as any downstream // crate will import them from their original source. + // FIXME(eddyb) the `Span` encoding should take that into account. !source_file.is_imported() }) .map(|source_file| { diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 74de31263d394..978ea20aa3397 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -73,6 +73,8 @@ struct AstValidator<'a> { /// these booleans. warning_period_57979_didnt_record_next_impl_trait: bool, warning_period_57979_impl_trait_in_proj: bool, + + lint_buffer: &'a mut lint::LintBuffer, } impl<'a> AstValidator<'a> { @@ -229,7 +231,7 @@ impl<'a> AstValidator<'a> { err.emit(); } - fn check_decl_no_pat(&self, decl: &FnDecl, report_err: ReportFn) { + fn check_decl_no_pat(decl: &FnDecl, mut report_err: F) { for arg in &decl.inputs { match arg.pat.kind { PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), _, None) | @@ -460,7 +462,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { match ty.kind { TyKind::BareFn(ref bfty) => { self.check_fn_decl(&bfty.decl); - self.check_decl_no_pat(&bfty.decl, |span, _| { + Self::check_decl_no_pat(&bfty.decl, |span, _| { struct_span_err!(self.session, span, E0561, "patterns aren't allowed in function pointer types").emit(); }); @@ -483,7 +485,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { TyKind::ImplTrait(_, ref bounds) => { if self.is_impl_trait_banned { if self.warning_period_57979_impl_trait_in_proj { - self.session.buffer_lint( + self.lint_buffer.buffer_lint( NESTED_IMPL_TRAIT, ty.id, ty.span, "`impl Trait` is not allowed in path parameters"); } else { @@ -494,7 +496,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if let Some(outer_impl_trait) = self.outer_impl_trait { if outer_impl_trait.should_warn_instead_of_error() { - self.session.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint_with_diagnostic( NESTED_IMPL_TRAIT, ty.id, ty.span, "nested `impl Trait` is not allowed", BuiltinLintDiagnostics::NestedImplTrait { @@ -634,9 +636,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_trait_fn_not_async(trait_item.span, sig.header.asyncness.node); self.check_trait_fn_not_const(sig.header.constness); if block.is_none() { - self.check_decl_no_pat(&sig.decl, |span, mut_ident| { + Self::check_decl_no_pat(&sig.decl, |span, mut_ident| { if mut_ident { - self.session.buffer_lint( + self.lint_buffer.buffer_lint( lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY, trait_item.id, span, "patterns aren't allowed in methods without bodies"); @@ -655,7 +657,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if attr::contains_name(&item.attrs, sym::warn_directory_ownership) { let lint = lint::builtin::LEGACY_DIRECTORY_OWNERSHIP; let msg = "cannot declare a new module at this location"; - self.session.buffer_lint(lint, item.id, item.span, msg); + self.lint_buffer.buffer_lint(lint, item.id, item.span, msg); } } ItemKind::Union(ref vdata, _) => { @@ -686,7 +688,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { match fi.kind { ForeignItemKind::Fn(ref decl, _) => { self.check_fn_decl(decl); - self.check_decl_no_pat(decl, |span, _| { + Self::check_decl_no_pat(decl, |span, _| { struct_span_err!(self.session, span, E0130, "patterns aren't allowed in foreign function declarations") .span_label(span, "pattern not allowed in foreign function").emit(); @@ -840,7 +842,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } -pub fn check_crate(session: &Session, krate: &Crate) -> bool { +pub fn check_crate(session: &Session, krate: &Crate, lints: &mut lint::LintBuffer) -> bool { let mut validator = AstValidator { session, has_proc_macro_decls: false, @@ -849,6 +851,7 @@ pub fn check_crate(session: &Session, krate: &Crate) -> bool { is_assoc_ty_bound_banned: false, warning_period_57979_didnt_record_next_impl_trait: false, warning_period_57979_impl_trait_in_proj: false, + lint_buffer: lints, }; visit::walk_crate(&mut validator, krate); diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs index f2aef2c12c7df..9ad63f28a8e16 100644 --- a/src/librustc_passes/dead.rs +++ b/src/librustc_passes/dead.rs @@ -578,7 +578,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) | hir::ItemKind::Trait(..) | - hir::ItemKind::Impl(..) => self.tcx.sess.source_map().def_span(item.span), + hir::ItemKind::Impl(..) => item.ident.span, _ => item.span, }; let participle = match item.kind { diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index 737589acf8d81..44b7a9fa047c2 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -232,7 +232,7 @@ impl Resolver<'_> { directive.span.is_dummy() => { if let ImportDirectiveSubclass::MacroUse = directive.subclass { if !directive.span.is_dummy() { - self.session.buffer_lint( + self.lint_buffer.buffer_lint( lint::builtin::MACRO_USE_EXTERN_CRATE, directive.id, directive.span, @@ -250,7 +250,7 @@ impl Resolver<'_> { ImportDirectiveSubclass::MacroUse => { let lint = lint::builtin::UNUSED_IMPORTS; let msg = "unused `#[macro_use]` import"; - self.session.buffer_lint(lint, directive.id, directive.span, msg); + self.lint_buffer.buffer_lint(lint, directive.id, directive.span, msg); } _ => {} } @@ -312,7 +312,7 @@ impl Resolver<'_> { "remove the unused import" }; - visitor.r.session.buffer_lint_with_diagnostic( + visitor.r.lint_buffer.buffer_lint_with_diagnostic( lint::builtin::UNUSED_IMPORTS, unused.use_tree_id, ms, diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 136ab1f0444fa..0d4e805045294 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -1511,7 +1511,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { if is_expected(ctor_res) && self.r.is_accessible_from(ctor_vis, self.parent_scope.module) { let lint = lint::builtin::LEGACY_CONSTRUCTOR_VISIBILITY; - self.r.session.buffer_lint(lint, id, span, + self.r.lint_buffer.buffer_lint(lint, id, span, "private struct constructors are not usable through \ re-exports in outer modules", ); @@ -1737,7 +1737,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { }; if result.base_res() == unqualified_result { let lint = lint::builtin::UNUSED_QUALIFICATIONS; - self.r.session.buffer_lint(lint, id, span, "unnecessary qualification") + self.r.lint_buffer.buffer_lint(lint, id, span, "unnecessary qualification") } } @@ -2074,7 +2074,7 @@ impl<'a> Resolver<'a> { let mut late_resolution_visitor = LateResolutionVisitor::new(self); visit::walk_crate(&mut late_resolution_visitor, krate); for (id, span) in late_resolution_visitor.unused_labels.iter() { - self.session.buffer_lint(lint::builtin::UNUSED_LABELS, *id, *span, "unused label"); + self.lint_buffer.buffer_lint(lint::builtin::UNUSED_LABELS, *id, *span, "unused label"); } } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 9239280634724..5d868e9274019 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -961,6 +961,8 @@ pub struct Resolver<'a> { /// Stores enum visibilities to properly build a reduced graph /// when visiting the correspondent variants. variant_vis: DefIdMap, + + lint_buffer: lint::LintBuffer, } /// Nothing really interesting here; it just provides memory for the rest of the crate. @@ -1080,6 +1082,10 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> { let expn_id = self.definitions.expansion_that_defined(def_id.index); self.has_derives(expn_id, derives) } + + fn lint_buffer(&mut self) -> &mut lint::LintBuffer { + &mut self.lint_buffer + } } impl<'a> Resolver<'a> { @@ -1226,10 +1232,15 @@ impl<'a> Resolver<'a> { features.declared_lib_features.iter().map(|(feat, ..)| *feat) .chain(features.declared_lang_features.iter().map(|(feat, ..)| *feat)) .collect(), - variant_vis: Default::default() + variant_vis: Default::default(), + lint_buffer: lint::LintBuffer::default(), } } + pub fn lint_buffer(&mut self) -> &mut lint::LintBuffer { + &mut self.lint_buffer + } + pub fn arenas() -> ResolverArenas<'a> { Default::default() } @@ -1652,7 +1663,7 @@ impl<'a> Resolver<'a> { match result { Ok(binding) => { if let Some(node_id) = poisoned { - self.session.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint_with_diagnostic( lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, node_id, ident.span, &format!("cannot find {} `{}` in this scope", ns.descr(), ident), @@ -2117,7 +2128,7 @@ impl<'a> Resolver<'a> { } fn lint_if_path_starts_with_module( - &self, + &mut self, crate_lint: CrateLint, path: &[Segment], path_span: Span, @@ -2168,7 +2179,7 @@ impl<'a> Resolver<'a> { let diag = lint::builtin::BuiltinLintDiagnostics ::AbsPathWithModule(diag_span); - self.session.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint_with_diagnostic( lint::builtin::ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, diag_id, diag_span, "absolute paths must start with `self`, `super`, \ @@ -2418,7 +2429,7 @@ impl<'a> Resolver<'a> { for &(span_use, span_def) in &self.macro_expanded_macro_export_errors { let msg = "macro-expanded `macro_export` macros from the current crate \ cannot be referred to by absolute paths"; - self.session.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint_with_diagnostic( lint::builtin::MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, CRATE_NODE_ID, span_use, msg, lint::builtin::BuiltinLintDiagnostics:: diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 94fe0cc57403e..98a1a7d5fa619 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -246,9 +246,9 @@ impl<'a> base::Resolver for Resolver<'a> { Ok(InvocationRes::Single(ext)) } - fn check_unused_macros(&self) { + fn check_unused_macros(&mut self) { for (&node_id, &span) in self.unused_macros.iter() { - self.session.buffer_lint( + self.lint_buffer.buffer_lint( lint::builtin::UNUSED_MACROS, node_id, span, "unused macro definition" ); } @@ -788,15 +788,17 @@ impl<'a> Resolver<'a> { } } - fn check_stability_and_deprecation(&self, ext: &SyntaxExtension, path: &ast::Path) { + fn check_stability_and_deprecation(&mut self, ext: &SyntaxExtension, path: &ast::Path) { let span = path.span; if let Some(stability) = &ext.stability { if let StabilityLevel::Unstable { reason, issue, is_soft } = stability.level { let feature = stability.feature; if !self.active_features.contains(&feature) && !span.allows_unstable(feature) { let node_id = ast::CRATE_NODE_ID; - let soft_handler = - |lint, span, msg: &_| self.session.buffer_lint(lint, node_id, span, msg); + let lint_buffer = &mut self.lint_buffer; + let soft_handler = |lint, span, msg: &_| { + lint_buffer.buffer_lint(lint, node_id, span, msg) + }; stability::report_unstable( self.session, feature, reason, issue, is_soft, span, soft_handler ); @@ -806,14 +808,14 @@ impl<'a> Resolver<'a> { let path = pprust::path_to_string(path); let (message, lint) = stability::rustc_deprecation_message(depr, &path); stability::early_report_deprecation( - self.session, &message, depr.suggestion, lint, span + &mut self.lint_buffer, &message, depr.suggestion, lint, span ); } } if let Some(depr) = &ext.deprecation { let path = pprust::path_to_string(&path); let (message, lint) = stability::deprecation_message(depr, &path); - stability::early_report_deprecation(self.session, &message, None, lint, span); + stability::early_report_deprecation(&mut self.lint_buffer, &message, None, lint, span); } } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 31340ddd68372..23648bc09d278 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -496,7 +496,7 @@ impl<'a> Resolver<'a> { if let (&NameBindingKind::Res(_, true), &NameBindingKind::Res(_, true)) = (&old_binding.kind, &binding.kind) { - this.session.buffer_lint_with_diagnostic( + this.lint_buffer.buffer_lint_with_diagnostic( DUPLICATE_MACRO_EXPORTS, CRATE_NODE_ID, binding.span, @@ -1147,7 +1147,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { re-exported (error E0365), consider declaring with \ `pub`", ident); - self.r.session.buffer_lint(PUB_USE_OF_PRIVATE_EXTERN_CRATE, + self.r.lint_buffer.buffer_lint(PUB_USE_OF_PRIVATE_EXTERN_CRATE, directive.id, directive.span, &msg); @@ -1272,7 +1272,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let mut redundant_spans: Vec<_> = redundant_span.present_items().collect(); redundant_spans.sort(); redundant_spans.dedup(); - self.r.session.buffer_lint_with_diagnostic( + self.r.lint_buffer.buffer_lint_with_diagnostic( UNUSED_IMPORTS, directive.id, directive.span, diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 18b103960c745..b4b8d4566d577 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -430,7 +430,7 @@ fn check_item_type( fn check_impl<'tcx>( tcx: TyCtxt<'tcx>, - item: &hir::Item, + item: &'tcx hir::Item, ast_self_ty: &hir::Ty, ast_trait_ref: &Option, ) { @@ -445,15 +445,18 @@ fn check_impl<'tcx>( // therefore don't need to be WF (the trait's `Self: Trait` predicate // won't hold). let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap(); - let trait_ref = - fcx.normalize_associated_types_in( - ast_trait_ref.path.span, &trait_ref); - let obligations = - ty::wf::trait_obligations(fcx, - fcx.param_env, - fcx.body_id, - &trait_ref, - ast_trait_ref.path.span); + let trait_ref = fcx.normalize_associated_types_in( + ast_trait_ref.path.span, + &trait_ref, + ); + let obligations = ty::wf::trait_obligations( + fcx, + fcx.param_env, + fcx.body_id, + &trait_ref, + ast_trait_ref.path.span, + Some(item), + ); for obligation in obligations { fcx.register_predicate(obligation); } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 7a8a209a5350c..3d380a5f1826c 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -479,10 +479,12 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let mut skip_add = false; if let ty::Opaque(defin_ty_def_id, _substs) = definition_ty.kind { - if def_id == defin_ty_def_id { - debug!("Skipping adding concrete definition for opaque type {:?} {:?}", - opaque_defn, defin_ty_def_id); - skip_add = true; + if let hir::OpaqueTyOrigin::TypeAlias = opaque_defn.origin { + if def_id == defin_ty_def_id { + debug!("Skipping adding concrete definition for opaque type {:?} {:?}", + opaque_defn, defin_ty_def_id); + skip_add = true; + } } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 00435d67184a3..d5fa0169d4ada 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1981,19 +1981,18 @@ fn predicates_defined_on( ); let inferred_outlives = tcx.inferred_outlives_of(def_id); if !inferred_outlives.is_empty() { - let span = tcx.def_span(def_id); debug!( "predicates_defined_on: inferred_outlives_of({:?}) = {:?}", def_id, inferred_outlives, ); - result.predicates = tcx.arena.alloc_from_iter( - result.predicates.iter().copied().chain( - // FIXME(eddyb) use better spans - maybe add `Span`s - // to `inferred_outlives_of` predicates as well? - inferred_outlives.iter().map(|&p| (p, span)), - ), - ); + if result.predicates.is_empty() { + result.predicates = inferred_outlives; + } else { + result.predicates = tcx.arena.alloc_from_iter( + result.predicates.iter().chain(inferred_outlives).copied(), + ); + } } debug!("predicates_defined_on({:?}) = {:?}", def_id, result); result diff --git a/src/librustc_typeck/outlives/explicit.rs b/src/librustc_typeck/outlives/explicit.rs index 83194144216ee..21e529f33cfd0 100644 --- a/src/librustc_typeck/outlives/explicit.rs +++ b/src/librustc_typeck/outlives/explicit.rs @@ -30,11 +30,17 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { let mut required_predicates = RequiredPredicates::default(); // process predicates and convert to `RequiredPredicates` entry, see below - for (pred, _) in predicates.predicates { - match pred { + for &(predicate, span) in predicates.predicates { + match predicate { ty::Predicate::TypeOutlives(predicate) => { let OutlivesPredicate(ref ty, ref reg) = predicate.skip_binder(); - insert_outlives_predicate(tcx, (*ty).into(), reg, &mut required_predicates) + insert_outlives_predicate( + tcx, + (*ty).into(), + reg, + span, + &mut required_predicates, + ) } ty::Predicate::RegionOutlives(predicate) => { @@ -43,6 +49,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { tcx, (*reg1).into(), reg2, + span, &mut required_predicates, ) } diff --git a/src/librustc_typeck/outlives/implicit_infer.rs b/src/librustc_typeck/outlives/implicit_infer.rs index 433d04ffa64ff..74048b8d20c82 100644 --- a/src/librustc_typeck/outlives/implicit_infer.rs +++ b/src/librustc_typeck/outlives/implicit_infer.rs @@ -4,6 +4,7 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::ty::subst::{GenericArg, Subst, GenericArgKind}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::util::nodemap::FxHashMap; +use syntax_pos::Span; use super::explicit::ExplicitPredicatesMap; use super::utils::*; @@ -79,9 +80,11 @@ impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for InferVisitor<'cx, 'tcx> { // (struct/enum/union) there will be outlive // requirements for adt_def. let field_ty = self.tcx.type_of(field_def.did); + let field_span = self.tcx.def_span(field_def.did); insert_required_predicates_to_be_wf( self.tcx, field_ty, + field_span, self.global_inferred_outlives, &mut item_required_predicates, &mut self.explicit_map, @@ -118,6 +121,7 @@ impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for InferVisitor<'cx, 'tcx> { fn insert_required_predicates_to_be_wf<'tcx>( tcx: TyCtxt<'tcx>, field_ty: Ty<'tcx>, + field_span: Span, global_inferred_outlives: &FxHashMap>, required_predicates: &mut RequiredPredicates<'tcx>, explicit_map: &mut ExplicitPredicatesMap<'tcx>, @@ -130,7 +134,7 @@ fn insert_required_predicates_to_be_wf<'tcx>( // We also want to calculate potential predicates for the T ty::Ref(region, rty, _) => { debug!("Ref"); - insert_outlives_predicate(tcx, rty.into(), region, required_predicates); + insert_outlives_predicate(tcx, rty.into(), region, field_span, required_predicates); } // For each Adt (struct/enum/union) type `Foo<'a, T>`, we @@ -158,7 +162,7 @@ fn insert_required_predicates_to_be_wf<'tcx>( // 'a` holds for `Foo`. debug!("Adt"); if let Some(unsubstituted_predicates) = global_inferred_outlives.get(&def.did) { - for unsubstituted_predicate in unsubstituted_predicates { + for (unsubstituted_predicate, &span) in unsubstituted_predicates { // `unsubstituted_predicate` is `U: 'b` in the // example above. So apply the substitution to // get `T: 'a` (or `predicate`): @@ -167,6 +171,7 @@ fn insert_required_predicates_to_be_wf<'tcx>( tcx, predicate.0, predicate.1, + span, required_predicates, ); } @@ -272,7 +277,7 @@ pub fn check_explicit_predicates<'tcx>( ); let explicit_predicates = explicit_map.explicit_predicates_of(tcx, def_id); - for outlives_predicate in explicit_predicates.iter() { + for (outlives_predicate, &span) in explicit_predicates { debug!("outlives_predicate = {:?}", &outlives_predicate); // Careful: If we are inferring the effects of a `dyn Trait<..>` @@ -320,6 +325,6 @@ pub fn check_explicit_predicates<'tcx>( let predicate = outlives_predicate.subst(tcx, substs); debug!("predicate = {:?}", &predicate); - insert_outlives_predicate(tcx, predicate.0.into(), predicate.1, required_predicates); + insert_outlives_predicate(tcx, predicate.0.into(), predicate.1, span, required_predicates); } } diff --git a/src/librustc_typeck/outlives/mod.rs b/src/librustc_typeck/outlives/mod.rs index cdb83eb328ac2..6b861656d7e2d 100644 --- a/src/librustc_typeck/outlives/mod.rs +++ b/src/librustc_typeck/outlives/mod.rs @@ -5,6 +5,7 @@ use rustc::ty::query::Providers; use rustc::ty::subst::GenericArgKind; use rustc::ty::{self, CratePredicatesMap, TyCtxt}; use syntax::symbol::sym; +use syntax_pos::Span; mod explicit; mod implicit_infer; @@ -23,7 +24,7 @@ pub fn provide(providers: &mut Providers<'_>) { fn inferred_outlives_of( tcx: TyCtxt<'_>, item_def_id: DefId, -) -> &[ty::Predicate<'_>] { +) -> &[(ty::Predicate<'_>, Span)] { let id = tcx .hir() .as_local_hir_id(item_def_id) @@ -43,7 +44,7 @@ fn inferred_outlives_of( if tcx.has_attr(item_def_id, sym::rustc_outlives) { let mut pred: Vec = predicates .iter() - .map(|out_pred| match out_pred { + .map(|(out_pred, _)| match out_pred { ty::Predicate::RegionOutlives(p) => p.to_string(), ty::Predicate::TypeOutlives(p) => p.to_string(), err => bug!("unexpected predicate {:?}", err), @@ -96,19 +97,19 @@ fn inferred_outlives_crate( let predicates = global_inferred_outlives .iter() .map(|(&def_id, set)| { - let predicates = tcx.arena.alloc_from_iter(set + let predicates = &*tcx.arena.alloc_from_iter(set .iter() .filter_map( - |ty::OutlivesPredicate(kind1, region2)| match kind1.unpack() { + |(ty::OutlivesPredicate(kind1, region2), &span)| match kind1.unpack() { GenericArgKind::Type(ty1) => { - Some(ty::Predicate::TypeOutlives(ty::Binder::bind( + Some((ty::Predicate::TypeOutlives(ty::Binder::bind( ty::OutlivesPredicate(ty1, region2) - ))) + )), span)) } GenericArgKind::Lifetime(region1) => { - Some(ty::Predicate::RegionOutlives( + Some((ty::Predicate::RegionOutlives( ty::Binder::bind(ty::OutlivesPredicate(region1, region2)) - )) + ), span)) } GenericArgKind::Const(_) => { // Generic consts don't impose any constraints. @@ -116,7 +117,7 @@ fn inferred_outlives_crate( } }, )); - (def_id, &*predicates) + (def_id, predicates) }).collect(); tcx.arena.alloc(ty::CratePredicatesMap { diff --git a/src/librustc_typeck/outlives/utils.rs b/src/librustc_typeck/outlives/utils.rs index d34605dc482a3..361116e96d0bf 100644 --- a/src/librustc_typeck/outlives/utils.rs +++ b/src/librustc_typeck/outlives/utils.rs @@ -2,12 +2,13 @@ use rustc::ty::outlives::Component; use rustc::ty::subst::{GenericArg, GenericArgKind}; use rustc::ty::{self, Region, RegionKind, Ty, TyCtxt}; use smallvec::smallvec; -use std::collections::BTreeSet; +use std::collections::BTreeMap; +use syntax_pos::Span; /// Tracks the `T: 'a` or `'a: 'a` predicates that we have inferred /// must be added to the struct header. pub type RequiredPredicates<'tcx> = - BTreeSet, ty::Region<'tcx>>>; + BTreeMap, ty::Region<'tcx>>, Span>; /// Given a requirement `T: 'a` or `'b: 'a`, deduce the /// outlives_component and add it to `required_predicates` @@ -15,6 +16,7 @@ pub fn insert_outlives_predicate<'tcx>( tcx: TyCtxt<'tcx>, kind: GenericArg<'tcx>, outlived_region: Region<'tcx>, + span: Span, required_predicates: &mut RequiredPredicates<'tcx>, ) { // If the `'a` region is bound within the field type itself, we @@ -53,6 +55,7 @@ pub fn insert_outlives_predicate<'tcx>( tcx, r.into(), outlived_region, + span, required_predicates, ); } @@ -73,7 +76,8 @@ pub fn insert_outlives_predicate<'tcx>( // where clause that `U: 'a`. let ty: Ty<'tcx> = param_ty.to_ty(tcx); required_predicates - .insert(ty::OutlivesPredicate(ty.into(), outlived_region)); + .entry(ty::OutlivesPredicate(ty.into(), outlived_region)) + .or_insert(span); } Component::Projection(proj_ty) => { @@ -88,7 +92,8 @@ pub fn insert_outlives_predicate<'tcx>( // Here we want to add an explicit `where ::Item: 'a`. let ty: Ty<'tcx> = tcx.mk_projection(proj_ty.item_def_id, proj_ty.substs); required_predicates - .insert(ty::OutlivesPredicate(ty.into(), outlived_region)); + .entry(ty::OutlivesPredicate(ty.into(), outlived_region)) + .or_insert(span); } Component::EscapingProjection(_) => { @@ -117,7 +122,8 @@ pub fn insert_outlives_predicate<'tcx>( if !is_free_region(tcx, r) { return; } - required_predicates.insert(ty::OutlivesPredicate(kind, outlived_region)); + required_predicates.entry(ty::OutlivesPredicate(kind, outlived_region)) + .or_insert(span); } GenericArgKind::Const(_) => { diff --git a/src/libsyntax_expand/base.rs b/src/libsyntax_expand/base.rs index 58edf23a5b1e2..95a7a42824406 100644 --- a/src/libsyntax_expand/base.rs +++ b/src/libsyntax_expand/base.rs @@ -868,7 +868,7 @@ pub trait Resolver { &mut self, invoc: &Invocation, eager_expansion_root: ExpnId, force: bool ) -> Result; - fn check_unused_macros(&self); + fn check_unused_macros(&mut self); fn has_derives(&self, expn_id: ExpnId, derives: SpecialDerives) -> bool; fn add_derives(&mut self, expn_id: ExpnId, derives: SpecialDerives); @@ -1063,7 +1063,7 @@ impl<'a> ExtCtxt<'a> { Symbol::intern(st) } - pub fn check_unused_macros(&self) { + pub fn check_unused_macros(&mut self) { self.resolver.check_unused_macros(); } diff --git a/src/test/compile-fail/chalkify/impl_wf.rs b/src/test/compile-fail/chalkify/impl_wf.rs index 96b1b2533712b..6bb4cf86e7986 100644 --- a/src/test/compile-fail/chalkify/impl_wf.rs +++ b/src/test/compile-fail/chalkify/impl_wf.rs @@ -25,6 +25,7 @@ impl Bar for Option { impl Bar for f32 { //~^ ERROR the trait bound `f32: Foo` is not satisfied type Item = f32; + //~^ ERROR the trait bound `f32: Foo` is not satisfied } trait Baz where U: Foo { } diff --git a/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr b/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr index c6d198dc458a6..5ab3dfb24496f 100644 --- a/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr +++ b/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr @@ -7,10 +7,10 @@ LL | #![plugin(lint_plugin_test)] = note: `#[warn(deprecated)]` on by default warning: function is never used: `lintme` - --> $DIR/lint-plugin-cmdline-allow.rs:10:1 + --> $DIR/lint-plugin-cmdline-allow.rs:10:4 | LL | fn lintme() { } - | ^^^^^^^^^^^ + | ^^^^^^ | note: lint level defined here --> $DIR/lint-plugin-cmdline-allow.rs:7:9 diff --git a/src/test/ui-fulldeps/lint-tool-cmdline-allow.stderr b/src/test/ui-fulldeps/lint-tool-cmdline-allow.stderr index 239732521d59e..3a9fd7c2867f2 100644 --- a/src/test/ui-fulldeps/lint-tool-cmdline-allow.stderr +++ b/src/test/ui-fulldeps/lint-tool-cmdline-allow.stderr @@ -19,10 +19,10 @@ LL | fn lintme() {} = note: `#[warn(clippy::test_lint)]` on by default warning: function is never used: `lintme` - --> $DIR/lint-tool-cmdline-allow.rs:10:1 + --> $DIR/lint-tool-cmdline-allow.rs:10:4 | LL | fn lintme() {} - | ^^^^^^^^^^^ + | ^^^^^^ | note: lint level defined here --> $DIR/lint-tool-cmdline-allow.rs:7:9 diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs new file mode 100644 index 0000000000000..9360d96f05e17 --- /dev/null +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs @@ -0,0 +1,11 @@ +trait Bar {} + +trait Foo { + type Assoc: Bar; +} + +impl Foo for () { + type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied +} + +fn main() {} diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr new file mode 100644 index 0000000000000..f1a2e343a7ec3 --- /dev/null +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `bool: Bar` is not satisfied + --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5 + | +LL | type Assoc: Bar; + | ----- associated type defined here +... +LL | impl Foo for () { + | --------------- in this `impl` item +LL | type Assoc = bool; + | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure.rs b/src/test/ui/associated-types/point-at-type-on-obligation-failure.rs new file mode 100644 index 0000000000000..dc43dbaf54b99 --- /dev/null +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure.rs @@ -0,0 +1,20 @@ +trait Bar { + type Ok; + type Sibling: Bar2; +} +trait Bar2 { + type Ok; +} + +struct Foo; +struct Foo2; + +impl Bar for Foo { + type Ok = (); //~ ERROR type mismatch resolving `::Ok == ()` + type Sibling = Foo2; +} +impl Bar2 for Foo2 { + type Ok = u32; +} + +fn main() {} diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr b/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr new file mode 100644 index 0000000000000..e4bd39c8ba62c --- /dev/null +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr @@ -0,0 +1,17 @@ +error[E0271]: type mismatch resolving `::Ok == ()` + --> $DIR/point-at-type-on-obligation-failure.rs:13:5 + | +LL | type Ok; + | -- associated type defined here +... +LL | impl Bar for Foo { + | ---------------- in this `impl` item +LL | type Ok = (); + | ^^^^^^^^^^^^^ expected u32, found () + | + = note: expected type `u32` + found type `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/coherence/impl-foreign-for-locally-defined-fundamental.rs b/src/test/ui/coherence/impl-foreign-for-locally-defined-fundamental.rs new file mode 100644 index 0000000000000..d461b5abd60ff --- /dev/null +++ b/src/test/ui/coherence/impl-foreign-for-locally-defined-fundamental.rs @@ -0,0 +1,16 @@ +#![feature(fundamental)] +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; + +#[fundamental] +struct Local; + +impl Remote for Local {} + +fn main() {} diff --git a/src/test/ui/coherence/impl-foreign-for-locally-defined-fundamental[foreign].rs b/src/test/ui/coherence/impl-foreign-for-locally-defined-fundamental[foreign].rs new file mode 100644 index 0000000000000..0a3d9e2e0e89c --- /dev/null +++ b/src/test/ui/coherence/impl-foreign-for-locally-defined-fundamental[foreign].rs @@ -0,0 +1,16 @@ +#![feature(fundamental)] +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; + +#[fundamental] +struct MyBox(T); + +impl Remote for MyBox {} + +fn main() {} diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs new file mode 100644 index 0000000000000..2b4f5e0975ac3 --- /dev/null +++ b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs @@ -0,0 +1,7 @@ +// Test that an `impl Trait` type that expands to itself is an error. + +fn test() -> impl Sized { //~ ERROR E0720 + test() +} + +fn main() {} diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr new file mode 100644 index 0000000000000..1b5dbd814a481 --- /dev/null +++ b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr @@ -0,0 +1,11 @@ +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type-direct.rs:3:14 + | +LL | fn test() -> impl Sized { + | ^^^^^^^^^^ expands to a recursive type + | + = note: type resolves to itself + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0720`. diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type.rs b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs similarity index 100% rename from src/test/ui/impl-trait/recursive-impl-trait-type.rs rename to src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr similarity index 76% rename from src/test/ui/impl-trait/recursive-impl-trait-type.stderr rename to src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr index 324607117dc50..b7ba0d6ab177c 100644 --- a/src/test/ui/impl-trait/recursive-impl-trait-type.stderr +++ b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr @@ -1,5 +1,5 @@ error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:6:22 + --> $DIR/recursive-impl-trait-type-indirect.rs:6:22 | LL | fn option(i: i32) -> impl Sized { | ^^^^^^^^^^ expands to a recursive type @@ -7,7 +7,7 @@ LL | fn option(i: i32) -> impl Sized { = note: expanded type is `std::option::Option<(impl Sized, i32)>` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:14:15 + --> $DIR/recursive-impl-trait-type-indirect.rs:14:15 | LL | fn tuple() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type @@ -15,7 +15,7 @@ LL | fn tuple() -> impl Sized { = note: expanded type is `(impl Sized,)` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:18:15 + --> $DIR/recursive-impl-trait-type-indirect.rs:18:15 | LL | fn array() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type @@ -23,7 +23,7 @@ LL | fn array() -> impl Sized { = note: expanded type is `[impl Sized; 1]` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:22:13 + --> $DIR/recursive-impl-trait-type-indirect.rs:22:13 | LL | fn ptr() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type @@ -31,7 +31,7 @@ LL | fn ptr() -> impl Sized { = note: expanded type is `*const impl Sized` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:26:16 + --> $DIR/recursive-impl-trait-type-indirect.rs:26:16 | LL | fn fn_ptr() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type @@ -39,47 +39,47 @@ LL | fn fn_ptr() -> impl Sized { = note: expanded type is `fn() -> impl Sized` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:30:25 + --> $DIR/recursive-impl-trait-type-indirect.rs:30:25 | LL | fn closure_capture() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type | - = note: expanded type is `[closure@$DIR/recursive-impl-trait-type.rs:32:5: 32:19 x:impl Sized]` + = note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:32:5: 32:19 x:impl Sized]` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:35:29 + --> $DIR/recursive-impl-trait-type-indirect.rs:35:29 | LL | fn closure_ref_capture() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type | - = note: expanded type is `[closure@$DIR/recursive-impl-trait-type.rs:37:5: 37:20 x:impl Sized]` + = note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:37:5: 37:20 x:impl Sized]` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:40:21 + --> $DIR/recursive-impl-trait-type-indirect.rs:40:21 | LL | fn closure_sig() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type | - = note: expanded type is `[closure@$DIR/recursive-impl-trait-type.rs:41:5: 41:21]` + = note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:41:5: 41:21]` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:44:23 + --> $DIR/recursive-impl-trait-type-indirect.rs:44:23 | LL | fn generator_sig() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type | - = note: expanded type is `[closure@$DIR/recursive-impl-trait-type.rs:45:5: 45:23]` + = note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:45:5: 45:23]` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:48:27 + --> $DIR/recursive-impl-trait-type-indirect.rs:48:27 | LL | fn generator_capture() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type | - = note: expanded type is `[generator@$DIR/recursive-impl-trait-type.rs:50:5: 50:26 x:impl Sized {()}]` + = note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:26 x:impl Sized {()}]` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:53:26 + --> $DIR/recursive-impl-trait-type-indirect.rs:53:26 | LL | fn substs_change() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type @@ -87,15 +87,15 @@ LL | fn substs_change() -> impl Sized { = note: expanded type is `(impl Sized,)` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:57:24 + --> $DIR/recursive-impl-trait-type-indirect.rs:57:24 | LL | fn generator_hold() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type | - = note: expanded type is `[generator@$DIR/recursive-impl-trait-type.rs:58:5: 62:6 {impl Sized, ()}]` + = note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:58:5: 62:6 {impl Sized, ()}]` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:69:26 + --> $DIR/recursive-impl-trait-type-indirect.rs:69:26 | LL | fn mutual_recursion() -> impl Sync { | ^^^^^^^^^ expands to a recursive type @@ -103,7 +103,7 @@ LL | fn mutual_recursion() -> impl Sync { = note: type resolves to itself error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:73:28 + --> $DIR/recursive-impl-trait-type-indirect.rs:73:28 | LL | fn mutual_recursion_b() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.rs b/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.rs similarity index 100% rename from src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.rs rename to src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.rs diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr similarity index 77% rename from src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr rename to src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr index 7572c6c1bf057..73c12f6137d24 100644 --- a/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr +++ b/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr @@ -1,5 +1,5 @@ error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:7:22 + --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:7:22 | LL | fn recursive_id() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type @@ -7,7 +7,7 @@ LL | fn recursive_id() -> impl Sized { = note: type resolves to itself error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:11:23 + --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:11:23 | LL | fn recursive_id2() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type @@ -15,7 +15,7 @@ LL | fn recursive_id2() -> impl Sized { = note: type resolves to itself error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:17:24 + --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:17:24 | LL | fn recursive_wrap() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type @@ -23,7 +23,7 @@ LL | fn recursive_wrap() -> impl Sized { = note: expanded type is `((impl Sized,),)` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:21:25 + --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:21:25 | LL | fn recursive_wrap2() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type diff --git a/src/test/ui/issues/issue-43784-associated-type.rs b/src/test/ui/issues/issue-43784-associated-type.rs index fb58ad6600f7e..92083d88f1b82 100644 --- a/src/test/ui/issues/issue-43784-associated-type.rs +++ b/src/test/ui/issues/issue-43784-associated-type.rs @@ -10,8 +10,8 @@ impl Partial for T::Assoc where { } -impl Complete for T { //~ ERROR the trait bound `T: std::marker::Copy` is not satisfied - type Assoc = T; +impl Complete for T { + type Assoc = T; //~ ERROR the trait bound `T: std::marker::Copy` is not satisfied } fn main() {} diff --git a/src/test/ui/issues/issue-43784-associated-type.stderr b/src/test/ui/issues/issue-43784-associated-type.stderr index e91e53499ce6c..393b012f5f8a7 100644 --- a/src/test/ui/issues/issue-43784-associated-type.stderr +++ b/src/test/ui/issues/issue-43784-associated-type.stderr @@ -1,10 +1,16 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied - --> $DIR/issue-43784-associated-type.rs:13:9 + --> $DIR/issue-43784-associated-type.rs:14:5 | +LL | type Assoc: Partial; + | ----- associated type defined here +... LL | impl Complete for T { - | - ^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` - | | - | help: consider restricting this bound: `T: std::marker::Copy` + | ---------------------- + | | | + | | help: consider restricting this bound: `T: std::marker::Copy` + | in this `impl` item +LL | type Assoc = T; + | ^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` error: aborting due to previous error diff --git a/src/test/ui/dead-code-alias-in-pat.rs b/src/test/ui/lint/dead-code/alias-in-pat.rs similarity index 100% rename from src/test/ui/dead-code-alias-in-pat.rs rename to src/test/ui/lint/dead-code/alias-in-pat.rs diff --git a/src/test/ui/lint-dead-code-associated-type.rs b/src/test/ui/lint/dead-code/associated-type.rs similarity index 100% rename from src/test/ui/lint-dead-code-associated-type.rs rename to src/test/ui/lint/dead-code/associated-type.rs diff --git a/src/test/ui/fail-no-dead-code.rs b/src/test/ui/lint/dead-code/basic.rs similarity index 100% rename from src/test/ui/fail-no-dead-code.rs rename to src/test/ui/lint/dead-code/basic.rs diff --git a/src/test/ui/fail-no-dead-code.stderr b/src/test/ui/lint/dead-code/basic.stderr similarity index 68% rename from src/test/ui/fail-no-dead-code.stderr rename to src/test/ui/lint/dead-code/basic.stderr index 8babcffaa8dd7..194398e5a07a5 100644 --- a/src/test/ui/fail-no-dead-code.stderr +++ b/src/test/ui/lint/dead-code/basic.stderr @@ -1,11 +1,11 @@ error: function is never used: `foo` - --> $DIR/fail-no-dead-code.rs:4:1 + --> $DIR/basic.rs:4:4 | LL | fn foo() { - | ^^^^^^^^ + | ^^^ | note: lint level defined here - --> $DIR/fail-no-dead-code.rs:1:9 + --> $DIR/basic.rs:1:9 | LL | #![deny(dead_code)] | ^^^^^^^^^ diff --git a/src/test/ui/dead-code-closure-bang.rs b/src/test/ui/lint/dead-code/closure-bang.rs similarity index 100% rename from src/test/ui/dead-code-closure-bang.rs rename to src/test/ui/lint/dead-code/closure-bang.rs diff --git a/src/test/ui/lint/lint-dead-code-const-and-self.rs b/src/test/ui/lint/dead-code/const-and-self.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-const-and-self.rs rename to src/test/ui/lint/dead-code/const-and-self.rs diff --git a/src/test/ui/lint/lint-dead-code-empty-unused-enum.rs b/src/test/ui/lint/dead-code/empty-unused-enum.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-empty-unused-enum.rs rename to src/test/ui/lint/dead-code/empty-unused-enum.rs diff --git a/src/test/ui/lint/lint-dead-code-empty-unused-enum.stderr b/src/test/ui/lint/dead-code/empty-unused-enum.stderr similarity index 67% rename from src/test/ui/lint/lint-dead-code-empty-unused-enum.stderr rename to src/test/ui/lint/dead-code/empty-unused-enum.stderr index 4e3bebfc48bde..44b0a8f613e27 100644 --- a/src/test/ui/lint/lint-dead-code-empty-unused-enum.stderr +++ b/src/test/ui/lint/dead-code/empty-unused-enum.stderr @@ -1,11 +1,11 @@ error: enum is never used: `E` - --> $DIR/lint-dead-code-empty-unused-enum.rs:3:1 + --> $DIR/empty-unused-enum.rs:3:6 | LL | enum E {} - | ^^^^^^ + | ^ | note: lint level defined here - --> $DIR/lint-dead-code-empty-unused-enum.rs:1:9 + --> $DIR/empty-unused-enum.rs:1:9 | LL | #![deny(unused)] | ^^^^^^ diff --git a/src/test/ui/lint/lint-dead-code-empty-unused-enum-pub.rs b/src/test/ui/lint/dead-code/empty-unused-public-enum.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-empty-unused-enum-pub.rs rename to src/test/ui/lint/dead-code/empty-unused-public-enum.rs diff --git a/src/test/ui/lint-dead-code-variant.rs b/src/test/ui/lint/dead-code/enum-variants.rs similarity index 100% rename from src/test/ui/lint-dead-code-variant.rs rename to src/test/ui/lint/dead-code/enum-variants.rs diff --git a/src/test/ui/lint/lint-dead-code-impl-trait.rs b/src/test/ui/lint/dead-code/impl-trait.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-impl-trait.rs rename to src/test/ui/lint/dead-code/impl-trait.rs diff --git a/src/test/ui/lint/lint-dead-code-impl-trait.stderr b/src/test/ui/lint/dead-code/impl-trait.stderr similarity index 71% rename from src/test/ui/lint/lint-dead-code-impl-trait.stderr rename to src/test/ui/lint/dead-code/impl-trait.stderr index 61d0954bf3146..f2a78cc65e26e 100644 --- a/src/test/ui/lint/lint-dead-code-impl-trait.stderr +++ b/src/test/ui/lint/dead-code/impl-trait.stderr @@ -1,11 +1,11 @@ error: type alias is never used: `Unused` - --> $DIR/lint-dead-code-impl-trait.rs:12:1 + --> $DIR/impl-trait.rs:12:1 | LL | type Unused = (); | ^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/lint-dead-code-impl-trait.rs:1:9 + --> $DIR/impl-trait.rs:1:9 | LL | #![deny(dead_code)] | ^^^^^^^^^ diff --git a/src/test/ui/dead-code-leading-underscore.rs b/src/test/ui/lint/dead-code/leading-underscore.rs similarity index 100% rename from src/test/ui/dead-code-leading-underscore.rs rename to src/test/ui/lint/dead-code/leading-underscore.rs diff --git a/src/test/ui/lint/lint-dead-code-1.rs b/src/test/ui/lint/dead-code/lint-dead-code-1.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-1.rs rename to src/test/ui/lint/dead-code/lint-dead-code-1.rs diff --git a/src/test/ui/lint/lint-dead-code-1.stderr b/src/test/ui/lint/dead-code/lint-dead-code-1.stderr similarity index 73% rename from src/test/ui/lint/lint-dead-code-1.stderr rename to src/test/ui/lint/dead-code/lint-dead-code-1.stderr index be96c697d9944..bac46a2e843cd 100644 --- a/src/test/ui/lint/lint-dead-code-1.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-1.stderr @@ -1,8 +1,8 @@ error: struct is never constructed: `Bar` - --> $DIR/lint-dead-code-1.rs:12:5 + --> $DIR/lint-dead-code-1.rs:12:16 | LL | pub struct Bar; - | ^^^^^^^^^^^^^^^ + | ^^^ | note: lint level defined here --> $DIR/lint-dead-code-1.rs:5:9 @@ -23,16 +23,16 @@ LL | const priv_const: isize = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: struct is never constructed: `PrivStruct` - --> $DIR/lint-dead-code-1.rs:35:1 + --> $DIR/lint-dead-code-1.rs:35:8 | LL | struct PrivStruct; - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ error: enum is never used: `priv_enum` - --> $DIR/lint-dead-code-1.rs:64:1 + --> $DIR/lint-dead-code-1.rs:64:6 | LL | enum priv_enum { foo2, bar2 } - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^ error: variant is never constructed: `bar3` --> $DIR/lint-dead-code-1.rs:67:5 @@ -41,28 +41,28 @@ LL | bar3 | ^^^^ error: function is never used: `priv_fn` - --> $DIR/lint-dead-code-1.rs:88:1 + --> $DIR/lint-dead-code-1.rs:88:4 | LL | fn priv_fn() { - | ^^^^^^^^^^^^ + | ^^^^^^^ error: function is never used: `foo` - --> $DIR/lint-dead-code-1.rs:93:1 + --> $DIR/lint-dead-code-1.rs:93:4 | LL | fn foo() { - | ^^^^^^^^ + | ^^^ error: function is never used: `bar` - --> $DIR/lint-dead-code-1.rs:98:1 + --> $DIR/lint-dead-code-1.rs:98:4 | LL | fn bar() { - | ^^^^^^^^ + | ^^^ error: function is never used: `baz` - --> $DIR/lint-dead-code-1.rs:102:1 + --> $DIR/lint-dead-code-1.rs:102:4 | LL | fn baz() -> impl Copy { - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^ error: aborting due to 10 previous errors diff --git a/src/test/ui/lint/lint-dead-code-2.rs b/src/test/ui/lint/dead-code/lint-dead-code-2.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-2.rs rename to src/test/ui/lint/dead-code/lint-dead-code-2.rs diff --git a/src/test/ui/lint/lint-dead-code-2.stderr b/src/test/ui/lint/dead-code/lint-dead-code-2.stderr similarity index 69% rename from src/test/ui/lint/lint-dead-code-2.stderr rename to src/test/ui/lint/dead-code/lint-dead-code-2.stderr index 1226f9823ac54..a578a76d9a075 100644 --- a/src/test/ui/lint/lint-dead-code-2.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-2.stderr @@ -1,8 +1,8 @@ error: function is never used: `dead_fn` - --> $DIR/lint-dead-code-2.rs:22:1 + --> $DIR/lint-dead-code-2.rs:22:4 | LL | fn dead_fn() {} - | ^^^^^^^^^^^^ + | ^^^^^^^ | note: lint level defined here --> $DIR/lint-dead-code-2.rs:2:9 @@ -11,16 +11,16 @@ LL | #![deny(dead_code)] | ^^^^^^^^^ error: function is never used: `dead_fn2` - --> $DIR/lint-dead-code-2.rs:25:1 + --> $DIR/lint-dead-code-2.rs:25:4 | LL | fn dead_fn2() {} - | ^^^^^^^^^^^^^ + | ^^^^^^^^ error: function is never used: `main` - --> $DIR/lint-dead-code-2.rs:38:1 + --> $DIR/lint-dead-code-2.rs:38:4 | LL | fn main() { - | ^^^^^^^^^ + | ^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/lint-dead-code-3.rs b/src/test/ui/lint/dead-code/lint-dead-code-3.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-3.rs rename to src/test/ui/lint/dead-code/lint-dead-code-3.rs diff --git a/src/test/ui/lint/lint-dead-code-3.stderr b/src/test/ui/lint/dead-code/lint-dead-code-3.stderr similarity index 80% rename from src/test/ui/lint/lint-dead-code-3.stderr rename to src/test/ui/lint/dead-code/lint-dead-code-3.stderr index 2408da0af89ea..569196fffdd50 100644 --- a/src/test/ui/lint/lint-dead-code-3.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-3.stderr @@ -1,8 +1,8 @@ error: struct is never constructed: `Foo` - --> $DIR/lint-dead-code-3.rs:13:1 + --> $DIR/lint-dead-code-3.rs:13:8 | LL | struct Foo; - | ^^^^^^^^^^^ + | ^^^ | note: lint level defined here --> $DIR/lint-dead-code-3.rs:3:9 @@ -17,16 +17,16 @@ LL | fn foo(&self) { | ^^^^^^^^^^^^^ error: function is never used: `bar` - --> $DIR/lint-dead-code-3.rs:20:1 + --> $DIR/lint-dead-code-3.rs:20:4 | LL | fn bar() { - | ^^^^^^^^ + | ^^^ error: enum is never used: `c_void` - --> $DIR/lint-dead-code-3.rs:59:1 + --> $DIR/lint-dead-code-3.rs:59:6 | LL | enum c_void {} - | ^^^^^^^^^^^ + | ^^^^^^ error: foreign function is never used: `free` --> $DIR/lint-dead-code-3.rs:61:5 diff --git a/src/test/ui/lint/lint-dead-code-4.rs b/src/test/ui/lint/dead-code/lint-dead-code-4.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-4.rs rename to src/test/ui/lint/dead-code/lint-dead-code-4.rs diff --git a/src/test/ui/lint/lint-dead-code-4.stderr b/src/test/ui/lint/dead-code/lint-dead-code-4.stderr similarity index 96% rename from src/test/ui/lint/lint-dead-code-4.stderr rename to src/test/ui/lint/dead-code/lint-dead-code-4.stderr index b7ceee99998d7..8eaf789f8f793 100644 --- a/src/test/ui/lint/lint-dead-code-4.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-4.stderr @@ -27,10 +27,10 @@ LL | | }, | |_____^ error: enum is never used: `ABC` - --> $DIR/lint-dead-code-4.rs:24:1 + --> $DIR/lint-dead-code-4.rs:24:6 | LL | enum ABC { - | ^^^^^^^^ + | ^^^ error: variant is never constructed: `I` --> $DIR/lint-dead-code-4.rs:36:5 diff --git a/src/test/ui/lint/lint-dead-code-5.rs b/src/test/ui/lint/dead-code/lint-dead-code-5.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-5.rs rename to src/test/ui/lint/dead-code/lint-dead-code-5.rs diff --git a/src/test/ui/lint/lint-dead-code-5.stderr b/src/test/ui/lint/dead-code/lint-dead-code-5.stderr similarity index 92% rename from src/test/ui/lint/lint-dead-code-5.stderr rename to src/test/ui/lint/dead-code/lint-dead-code-5.stderr index 740cfde2c069f..9670d8e7a32e3 100644 --- a/src/test/ui/lint/lint-dead-code-5.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-5.stderr @@ -23,10 +23,10 @@ LL | Variant6(isize), | ^^^^^^^^^^^^^^^ error: enum is never used: `Enum3` - --> $DIR/lint-dead-code-5.rs:18:1 + --> $DIR/lint-dead-code-5.rs:18:6 | LL | enum Enum3 { - | ^^^^^^^^^^ + | ^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/lint/dead-code/newline-span.rs b/src/test/ui/lint/dead-code/newline-span.rs new file mode 100644 index 0000000000000..a4342056419d7 --- /dev/null +++ b/src/test/ui/lint/dead-code/newline-span.rs @@ -0,0 +1,19 @@ +#![deny(dead_code)] + +fn unused() { //~ error: function is never used: + println!("blah"); +} + +fn unused2(var: i32) { //~ error: function is never used: + println!("foo {}", var); +} + +fn unused3( //~ error: function is never used: + var: i32, +) { + println!("bar {}", var); +} + +fn main() { + println!("Hello world!"); +} diff --git a/src/test/ui/lint/dead-code/newline-span.stderr b/src/test/ui/lint/dead-code/newline-span.stderr new file mode 100644 index 0000000000000..c5d0d60506744 --- /dev/null +++ b/src/test/ui/lint/dead-code/newline-span.stderr @@ -0,0 +1,26 @@ +error: function is never used: `unused` + --> $DIR/newline-span.rs:3:4 + | +LL | fn unused() { + | ^^^^^^ + | +note: lint level defined here + --> $DIR/newline-span.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: function is never used: `unused2` + --> $DIR/newline-span.rs:7:4 + | +LL | fn unused2(var: i32) { + | ^^^^^^^ + +error: function is never used: `unused3` + --> $DIR/newline-span.rs:11:4 + | +LL | fn unused3( + | ^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/dead-code-tuple-struct-field.rs b/src/test/ui/lint/dead-code/tuple-struct-field.rs similarity index 100% rename from src/test/ui/dead-code-tuple-struct-field.rs rename to src/test/ui/lint/dead-code/tuple-struct-field.rs diff --git a/src/test/ui/lint/lint-dead-code-type-alias.rs b/src/test/ui/lint/dead-code/type-alias.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-type-alias.rs rename to src/test/ui/lint/dead-code/type-alias.rs diff --git a/src/test/ui/lint/lint-dead-code-type-alias.stderr b/src/test/ui/lint/dead-code/type-alias.stderr similarity index 71% rename from src/test/ui/lint/lint-dead-code-type-alias.stderr rename to src/test/ui/lint/dead-code/type-alias.stderr index 4198ddfb6cb03..82df23bd9448b 100644 --- a/src/test/ui/lint/lint-dead-code-type-alias.stderr +++ b/src/test/ui/lint/dead-code/type-alias.stderr @@ -1,11 +1,11 @@ error: type alias is never used: `Unused` - --> $DIR/lint-dead-code-type-alias.rs:4:1 + --> $DIR/type-alias.rs:4:1 | LL | type Unused = u8; | ^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/lint-dead-code-type-alias.rs:1:9 + --> $DIR/type-alias.rs:1:9 | LL | #![deny(dead_code)] | ^^^^^^^^^ diff --git a/src/test/ui/lint/lint-dead-code-unused-enum.rs b/src/test/ui/lint/dead-code/unused-enum.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-unused-enum.rs rename to src/test/ui/lint/dead-code/unused-enum.rs diff --git a/src/test/ui/lint/lint-dead-code-unused-enum.stderr b/src/test/ui/lint/dead-code/unused-enum.stderr similarity index 61% rename from src/test/ui/lint/lint-dead-code-unused-enum.stderr rename to src/test/ui/lint/dead-code/unused-enum.stderr index ea711e7b05ee6..142c2ccb99b05 100644 --- a/src/test/ui/lint/lint-dead-code-unused-enum.stderr +++ b/src/test/ui/lint/dead-code/unused-enum.stderr @@ -1,27 +1,27 @@ error: struct is never constructed: `F` - --> $DIR/lint-dead-code-unused-enum.rs:3:1 + --> $DIR/unused-enum.rs:3:8 | LL | struct F; - | ^^^^^^^^^ + | ^ | note: lint level defined here - --> $DIR/lint-dead-code-unused-enum.rs:1:9 + --> $DIR/unused-enum.rs:1:9 | LL | #![deny(unused)] | ^^^^^^ = note: `#[deny(dead_code)]` implied by `#[deny(unused)]` error: struct is never constructed: `B` - --> $DIR/lint-dead-code-unused-enum.rs:4:1 + --> $DIR/unused-enum.rs:4:8 | LL | struct B; - | ^^^^^^^^^ + | ^ error: enum is never used: `E` - --> $DIR/lint-dead-code-unused-enum.rs:6:1 + --> $DIR/unused-enum.rs:6:6 | LL | enum E { - | ^^^^^^ + | ^ error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/lint-dead-code-unused-variant.rs b/src/test/ui/lint/dead-code/unused-struct-variant.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-unused-variant.rs rename to src/test/ui/lint/dead-code/unused-struct-variant.rs diff --git a/src/test/ui/lint/lint-dead-code-unused-variant.stderr b/src/test/ui/lint/dead-code/unused-struct-variant.stderr similarity index 73% rename from src/test/ui/lint/lint-dead-code-unused-variant.stderr rename to src/test/ui/lint/dead-code/unused-struct-variant.stderr index 919996ec30020..0037592e3de06 100644 --- a/src/test/ui/lint/lint-dead-code-unused-variant.stderr +++ b/src/test/ui/lint/dead-code/unused-struct-variant.stderr @@ -1,11 +1,11 @@ error: variant is never constructed: `Bar` - --> $DIR/lint-dead-code-unused-variant.rs:8:5 + --> $DIR/unused-struct-variant.rs:8:5 | LL | Bar(B), | ^^^^^^ | note: lint level defined here - --> $DIR/lint-dead-code-unused-variant.rs:1:9 + --> $DIR/unused-struct-variant.rs:1:9 | LL | #![deny(unused)] | ^^^^^^ diff --git a/src/test/ui/lint/lint-dead-code-unused-variant-pub.rs b/src/test/ui/lint/dead-code/unused-variant-pub.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-unused-variant-pub.rs rename to src/test/ui/lint/dead-code/unused-variant-pub.rs diff --git a/src/test/ui/lint/lint-dead-code-variant.rs b/src/test/ui/lint/dead-code/unused-variant.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-variant.rs rename to src/test/ui/lint/dead-code/unused-variant.rs diff --git a/src/test/ui/lint/lint-dead-code-variant.stderr b/src/test/ui/lint/dead-code/unused-variant.stderr similarity index 72% rename from src/test/ui/lint/lint-dead-code-variant.stderr rename to src/test/ui/lint/dead-code/unused-variant.stderr index a79432dc68d6a..2167b9d910d94 100644 --- a/src/test/ui/lint/lint-dead-code-variant.stderr +++ b/src/test/ui/lint/dead-code/unused-variant.stderr @@ -1,11 +1,11 @@ error: variant is never constructed: `Variant1` - --> $DIR/lint-dead-code-variant.rs:5:5 + --> $DIR/unused-variant.rs:5:5 | LL | Variant1, | ^^^^^^^^ | note: lint level defined here - --> $DIR/lint-dead-code-variant.rs:1:9 + --> $DIR/unused-variant.rs:1:9 | LL | #![deny(dead_code)] | ^^^^^^^^^ diff --git a/src/test/ui/fail-no-dead-code-core.rs b/src/test/ui/lint/dead-code/with-core-crate.rs similarity index 100% rename from src/test/ui/fail-no-dead-code-core.rs rename to src/test/ui/lint/dead-code/with-core-crate.rs diff --git a/src/test/ui/fail-no-dead-code-core.stderr b/src/test/ui/lint/dead-code/with-core-crate.stderr similarity index 65% rename from src/test/ui/fail-no-dead-code-core.stderr rename to src/test/ui/lint/dead-code/with-core-crate.stderr index 2540242f9f68b..0b6ab67d9bfa5 100644 --- a/src/test/ui/fail-no-dead-code-core.stderr +++ b/src/test/ui/lint/dead-code/with-core-crate.stderr @@ -1,11 +1,11 @@ error: function is never used: `foo` - --> $DIR/fail-no-dead-code-core.rs:7:1 + --> $DIR/with-core-crate.rs:7:4 | LL | fn foo() { - | ^^^^^^^^ + | ^^^ | note: lint level defined here - --> $DIR/fail-no-dead-code-core.rs:1:9 + --> $DIR/with-core-crate.rs:1:9 | LL | #![deny(dead_code)] | ^^^^^^^^^ diff --git a/src/test/ui/dead-code-impl.rs b/src/test/ui/lint/dead-code/with-impl.rs similarity index 100% rename from src/test/ui/dead-code-impl.rs rename to src/test/ui/lint/dead-code/with-impl.rs diff --git a/src/test/ui/path-lookahead.rs b/src/test/ui/path-lookahead.rs index fd7509a623e31..86bcb08de404e 100644 --- a/src/test/ui/path-lookahead.rs +++ b/src/test/ui/path-lookahead.rs @@ -1,14 +1,14 @@ // run-pass - -#![warn(unused)] +#![allow(dead_code)] +#![warn(unused_parens)] // Parser test for #37765 -fn with_parens(arg: T) -> String { //~WARN function is never used: `with_parens` +fn with_parens(arg: T) -> String { return (::to_string(&arg)); //~WARN unnecessary parentheses around `return` value } -fn no_parens(arg: T) -> String { //~WARN function is never used: `no_parens` +fn no_parens(arg: T) -> String { return ::to_string(&arg); } diff --git a/src/test/ui/path-lookahead.stderr b/src/test/ui/path-lookahead.stderr index 197848e428a25..caf9e8303ea37 100644 --- a/src/test/ui/path-lookahead.stderr +++ b/src/test/ui/path-lookahead.stderr @@ -7,26 +7,6 @@ LL | return (::to_string(&arg)); note: lint level defined here --> $DIR/path-lookahead.rs:3:9 | -LL | #![warn(unused)] - | ^^^^^^ - = note: `#[warn(unused_parens)]` implied by `#[warn(unused)]` - -warning: function is never used: `with_parens` - --> $DIR/path-lookahead.rs:7:1 - | -LL | fn with_parens(arg: T) -> String { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: lint level defined here - --> $DIR/path-lookahead.rs:3:9 - | -LL | #![warn(unused)] - | ^^^^^^ - = note: `#[warn(dead_code)]` implied by `#[warn(unused)]` - -warning: function is never used: `no_parens` - --> $DIR/path-lookahead.rs:11:1 - | -LL | fn no_parens(arg: T) -> String { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #![warn(unused_parens)] + | ^^^^^^^^^^^^^ diff --git a/src/test/ui/span/macro-span-replacement.stderr b/src/test/ui/span/macro-span-replacement.stderr index 8b65e798b6ef5..439aedb4da4d2 100644 --- a/src/test/ui/span/macro-span-replacement.stderr +++ b/src/test/ui/span/macro-span-replacement.stderr @@ -1,11 +1,8 @@ warning: struct is never constructed: `S` - --> $DIR/macro-span-replacement.rs:7:14 + --> $DIR/macro-span-replacement.rs:7:12 | LL | $b $a; - | ^ -... -LL | m!(S struct); - | ------------- in this macro invocation + | ^^ | note: lint level defined here --> $DIR/macro-span-replacement.rs:3:9 diff --git a/src/test/ui/span/unused-warning-point-at-signature.rs b/src/test/ui/span/unused-warning-point-at-identifier.rs similarity index 84% rename from src/test/ui/span/unused-warning-point-at-signature.rs rename to src/test/ui/span/unused-warning-point-at-identifier.rs index 3af272a012eb2..d4d5bc1cbc8f1 100644 --- a/src/test/ui/span/unused-warning-point-at-signature.rs +++ b/src/test/ui/span/unused-warning-point-at-identifier.rs @@ -20,8 +20,8 @@ fn func() -> usize { //~ WARN function is never used 3 } -fn //~ WARN function is never used -func_complete_span() +fn +func_complete_span() //~ WARN function is never used -> usize { 3 diff --git a/src/test/ui/span/unused-warning-point-at-signature.stderr b/src/test/ui/span/unused-warning-point-at-identifier.stderr similarity index 52% rename from src/test/ui/span/unused-warning-point-at-signature.stderr rename to src/test/ui/span/unused-warning-point-at-identifier.stderr index 83e2ec1987b47..a4715d4adeb88 100644 --- a/src/test/ui/span/unused-warning-point-at-signature.stderr +++ b/src/test/ui/span/unused-warning-point-at-identifier.stderr @@ -1,36 +1,31 @@ warning: enum is never used: `Enum` - --> $DIR/unused-warning-point-at-signature.rs:5:1 + --> $DIR/unused-warning-point-at-identifier.rs:5:6 | LL | enum Enum { - | ^^^^^^^^^ + | ^^^^ | note: lint level defined here - --> $DIR/unused-warning-point-at-signature.rs:3:9 + --> $DIR/unused-warning-point-at-identifier.rs:3:9 | LL | #![warn(unused)] | ^^^^^^ = note: `#[warn(dead_code)]` implied by `#[warn(unused)]` warning: struct is never constructed: `Struct` - --> $DIR/unused-warning-point-at-signature.rs:12:1 + --> $DIR/unused-warning-point-at-identifier.rs:12:8 | LL | struct Struct { - | ^^^^^^^^^^^^^ + | ^^^^^^ warning: function is never used: `func` - --> $DIR/unused-warning-point-at-signature.rs:19:1 + --> $DIR/unused-warning-point-at-identifier.rs:19:4 | LL | fn func() -> usize { - | ^^^^^^^^^^^^^^^^^^ + | ^^^^ warning: function is never used: `func_complete_span` - --> $DIR/unused-warning-point-at-signature.rs:23:1 + --> $DIR/unused-warning-point-at-identifier.rs:24:1 | -LL | / fn -LL | | func_complete_span() -LL | | -> usize -LL | | { -LL | | 3 -LL | | } - | |_^ +LL | func_complete_span() + | ^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs index 265ccb3125ca3..394512c579474 100644 --- a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs +++ b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs @@ -16,10 +16,10 @@ struct ParentWrapper(T); impl> Parent for ParentWrapper { //~^ ERROR the trait bound `::Assoc: Child` is not satisfied - //~| ERROR the trait bound `::Assoc: Child` is not satisfied type Ty = A; type Assoc = ChildWrapper; //~^ ERROR the trait bound `::Assoc: Child` is not satisfied + //~| ERROR the trait bound `::Assoc: Child` is not satisfied } fn main() {} diff --git a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr index bdea8ab97e5b5..c6f2e5cda66af 100644 --- a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr +++ b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr @@ -9,25 +9,31 @@ LL | impl> Parent for ParentWrapper { | _| | | LL | | -LL | | LL | | type Ty = A; LL | | type Assoc = ChildWrapper; LL | | +LL | | LL | | } | |_^ the trait `Child` is not implemented for `::Assoc` error[E0277]: the trait bound `::Assoc: Child` is not satisfied - --> $DIR/missing-assoc-type-bound-restriction.rs:17:28 + --> $DIR/missing-assoc-type-bound-restriction.rs:20:5 | +LL | type Assoc: Child; + | ----- associated type defined here +... LL | impl> Parent for ParentWrapper { - | ^^^^^^ - help: consider further restricting the associated type: `where ::Assoc: Child` - | | - | the trait `Child` is not implemented for `::Assoc` + | ------------------------------------------------------- help: consider further restricting the associated type: `where ::Assoc: Child` + | | + | in this `impl` item +... +LL | type Assoc = ChildWrapper; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Child` is not implemented for `::Assoc` | = note: required because of the requirements on the impl of `Child` for `ChildWrapper<::Assoc>` error[E0277]: the trait bound `::Assoc: Child` is not satisfied - --> $DIR/missing-assoc-type-bound-restriction.rs:21:5 + --> $DIR/missing-assoc-type-bound-restriction.rs:20:5 | LL | trait Parent { | ------------ required by `Parent` diff --git a/src/test/ui/test-attrs/test-warns-dead-code.stderr b/src/test/ui/test-attrs/test-warns-dead-code.stderr index 62e99225dd902..cb118cdb4103c 100644 --- a/src/test/ui/test-attrs/test-warns-dead-code.stderr +++ b/src/test/ui/test-attrs/test-warns-dead-code.stderr @@ -1,8 +1,8 @@ error: function is never used: `dead` - --> $DIR/test-warns-dead-code.rs:5:1 + --> $DIR/test-warns-dead-code.rs:5:4 | LL | fn dead() {} - | ^^^^^^^^^ + | ^^^^ | note: lint level defined here --> $DIR/test-warns-dead-code.rs:3:9 diff --git a/src/test/ui/thread-local-not-in-prelude.rs b/src/test/ui/thread-local-not-in-prelude.rs index 039749826256f..e5ed09c600bf9 100644 --- a/src/test/ui/thread-local-not-in-prelude.rs +++ b/src/test/ui/thread-local-not-in-prelude.rs @@ -1,5 +1,4 @@ // run-pass - #![no_std] extern crate std; diff --git a/src/test/ui/traits/cycle-cache-err-60010.rs b/src/test/ui/traits/cycle-cache-err-60010.rs index 45aa1b3c52239..cbddef082be67 100644 --- a/src/test/ui/traits/cycle-cache-err-60010.rs +++ b/src/test/ui/traits/cycle-cache-err-60010.rs @@ -27,8 +27,8 @@ struct SalsaStorage { _parse: >::Data, //~ ERROR overflow } -impl Database for RootDatabase { //~ ERROR overflow - type Storage = SalsaStorage; +impl Database for RootDatabase { + type Storage = SalsaStorage; //~ ERROR overflow } impl HasQueryGroup for RootDatabase {} impl Query for ParseQuery diff --git a/src/test/ui/traits/cycle-cache-err-60010.stderr b/src/test/ui/traits/cycle-cache-err-60010.stderr index 9192f7ba2e3b0..f439de8826117 100644 --- a/src/test/ui/traits/cycle-cache-err-60010.stderr +++ b/src/test/ui/traits/cycle-cache-err-60010.stderr @@ -7,10 +7,15 @@ LL | _parse: >::Data, = note: required because of the requirements on the impl of `Query` for `ParseQuery` error[E0275]: overflow evaluating the requirement `RootDatabase: SourceDatabase` - --> $DIR/cycle-cache-err-60010.rs:30:6 + --> $DIR/cycle-cache-err-60010.rs:31:5 | +LL | type Storage; + | ------- associated type defined here +... LL | impl Database for RootDatabase { - | ^^^^^^^^ + | ------------------------------ in this `impl` item +LL | type Storage = SalsaStorage; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: required because of the requirements on the impl of `Query` for `ParseQuery` = note: required because it appears within the type `SalsaStorage` diff --git a/src/test/ui/dead-code-ret.rs b/src/test/ui/unreachable-code-ret.rs similarity index 100% rename from src/test/ui/dead-code-ret.rs rename to src/test/ui/unreachable-code-ret.rs diff --git a/src/test/ui/dead-code-ret.stderr b/src/test/ui/unreachable-code-ret.stderr similarity index 86% rename from src/test/ui/dead-code-ret.stderr rename to src/test/ui/unreachable-code-ret.stderr index 83841131599b2..c22342ce7218d 100644 --- a/src/test/ui/dead-code-ret.stderr +++ b/src/test/ui/unreachable-code-ret.stderr @@ -1,5 +1,5 @@ error: unreachable statement - --> $DIR/dead-code-ret.rs:7:5 + --> $DIR/unreachable-code-ret.rs:7:5 | LL | return; | ------ any code following this expression is unreachable @@ -7,7 +7,7 @@ LL | println!("Paul is dead"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement | note: lint level defined here - --> $DIR/dead-code-ret.rs:3:9 + --> $DIR/unreachable-code-ret.rs:3:9 | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^