diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index e01e80939cad7..aa213cd072058 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1655,11 +1655,11 @@ impl HandlerInner { let backtrace = std::env::var_os("RUST_BACKTRACE").map_or(true, |x| &x != "0"); for bug in bugs { if let Some(file) = self.ice_file.as_ref() - && let Ok(mut out) = std::fs::File::options().append(true).open(file) + && let Ok(mut out) = std::fs::File::options().create(true).append(true).open(file) { let _ = write!( &mut out, - "\n\ndelayed span bug: {}\n{}", + "delayed span bug: {}\n{}\n", bug.inner.styled_message().iter().filter_map(|(msg, _)| msg.as_str()).collect::(), &bug.note ); diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 919092ecb1649..a3b80147ffdef 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -756,7 +756,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( ); ocx.resolve_regions_and_report_errors(impl_m_def_id, &outlives_env)?; - let mut collected_tys = FxHashMap::default(); + let mut remapped_types = FxHashMap::default(); for (def_id, (ty, args)) in collected_types { match infcx.fully_resolve((ty, args)) { Ok((ty, args)) => { @@ -806,19 +806,37 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( Ok(ty) => ty, Err(guar) => Ty::new_error(tcx, guar), }; - collected_tys.insert(def_id, ty::EarlyBinder::bind(ty)); + remapped_types.insert(def_id, ty::EarlyBinder::bind(ty)); } Err(err) => { let reported = tcx.sess.delay_span_bug( return_span, format!("could not fully resolve: {ty} => {err:?}"), ); - collected_tys.insert(def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, reported))); + remapped_types.insert(def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, reported))); } } } - Ok(&*tcx.arena.alloc(collected_tys)) + // We may not collect all RPITITs that we see in the HIR for a trait signature + // because an RPITIT was located within a missing item. Like if we have a sig + // returning `-> Missing`, that gets converted to `-> [type error]`, + // and when walking through the signature we end up never collecting the def id + // of the `impl Sized`. Insert that here, so we don't ICE later. + for assoc_item in tcx.associated_types_for_impl_traits_in_associated_fn(trait_m.def_id) { + if !remapped_types.contains_key(assoc_item) { + remapped_types.insert( + *assoc_item, + ty::EarlyBinder::bind(Ty::new_error_with_message( + tcx, + return_span, + "missing synthetic item for RPITIT", + )), + ); + } + } + + Ok(&*tcx.arena.alloc(remapped_types)) } struct ImplTraitInTraitCollector<'a, 'tcx> { diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index a475972219966..c68f2d94f3521 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -531,8 +531,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; } - let up_to_rcvr_span = segment.ident.span.until(callee_expr.span); - let rest_span = callee_expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi()); + let Some(callee_expr_span) = callee_expr.span.find_ancestor_inside(call_expr.span) + else { + return; + }; + let up_to_rcvr_span = segment.ident.span.until(callee_expr_span); + let rest_span = callee_expr_span.shrink_to_hi().to(call_expr.span.shrink_to_hi()); let rest_snippet = if let Some(first) = rest.first() { self.tcx .sess diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index 7144084c78ebe..8cd1b82130b01 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -243,12 +243,18 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => { let mut err = self.report_concrete_failure(*parent, sub, sup); - let trait_item_span = self.tcx.def_span(trait_item_def_id); - let item_name = self.tcx.item_name(impl_item_def_id.to_def_id()); - err.span_label( - trait_item_span, - format!("definition of `{}` from trait", item_name), - ); + + // Don't mention the item name if it's an RPITIT, since that'll just confuse + // folks. + if !self.tcx.is_impl_trait_in_trait(impl_item_def_id.to_def_id()) { + let trait_item_span = self.tcx.def_span(trait_item_def_id); + let item_name = self.tcx.item_name(impl_item_def_id.to_def_id()); + err.span_label( + trait_item_span, + format!("definition of `{}` from trait", item_name), + ); + } + self.suggest_copy_trait_method_bounds( trait_item_def_id, impl_item_def_id, diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs index 5baeb1ee0cf7b..1913421f54c93 100644 --- a/compiler/rustc_middle/src/middle/privacy.rs +++ b/compiler/rustc_middle/src/middle/privacy.rs @@ -178,7 +178,12 @@ impl EffectiveVisibilities { // All effective visibilities except `reachable_through_impl_trait` are limited to // nominal visibility. For some items nominal visibility doesn't make sense so we // don't check this condition for them. - if !matches!(tcx.def_kind(def_id), DefKind::Impl { .. }) { + let is_impl = matches!(tcx.def_kind(def_id), DefKind::Impl { .. }); + let is_associated_item_in_trait_impl = tcx + .impl_of_method(def_id.to_def_id()) + .and_then(|impl_id| tcx.trait_id_of_impl(impl_id)) + .is_some(); + if !is_impl && !is_associated_item_in_trait_impl { let nominal_vis = tcx.visibility(def_id); if !nominal_vis.is_at_least(ev.reachable, tcx) { span_bug!( @@ -186,7 +191,7 @@ impl EffectiveVisibilities { "{:?}: reachable {:?} > nominal {:?}", def_id, ev.reachable, - nominal_vis + nominal_vis, ); } } diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 35cf9ea5f91cd..deebf5345bac9 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -11,7 +11,7 @@ use rustc_middle::ty::TyCtxt; use rustc_span::source_map::original_sp; use rustc_span::{BytePos, ExpnKind, MacroKind, Span, Symbol}; -use std::cell::RefCell; +use std::cell::OnceCell; use std::cmp::Ordering; #[derive(Debug, Copy, Clone)] @@ -67,7 +67,7 @@ impl CoverageStatement { pub(super) struct CoverageSpan { pub span: Span, pub expn_span: Span, - pub current_macro_or_none: RefCell>>, + pub current_macro_or_none: OnceCell>, pub bcb: BasicCoverageBlock, pub coverage_statements: Vec, pub is_closure: bool, @@ -175,8 +175,7 @@ impl CoverageSpan { /// If the span is part of a macro, returns the macro name symbol. pub fn current_macro(&self) -> Option { self.current_macro_or_none - .borrow_mut() - .get_or_insert_with(|| { + .get_or_init(|| { if let ExpnKind::Macro(MacroKind::Bang, current_macro) = self.expn_span.ctxt().outer_expn_data().kind { diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 4a54423217422..780f7ea426f7b 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -346,8 +346,16 @@ fn associated_type_for_impl_trait_in_impl( ) -> LocalDefId { let impl_local_def_id = tcx.local_parent(impl_fn_def_id); - // FIXME fix the span, we probably want the def_id of the return type of the function - let span = tcx.def_span(impl_fn_def_id); + let decl = tcx + .hir() + .find_by_def_id(impl_fn_def_id) + .expect("expected item") + .fn_decl() + .expect("expected decl"); + let span = match decl.output { + hir::FnRetTy::DefaultReturn(_) => tcx.def_span(impl_fn_def_id), + hir::FnRetTy::Return(ty) => ty.span, + }; let impl_assoc_ty = tcx.at(span).create_def(impl_local_def_id, DefPathData::ImplTraitAssocTy); let local_def_id = impl_assoc_ty.def_id(); diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 0e90d618ad434..15285465c713a 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -300,7 +300,7 @@ pub fn panic_hook_with_disk_dump(info: &PanicInfo<'_>, path: Option<&crate::path }; if let Some(path) = path - && let Ok(mut out) = crate::fs::File::options().create(true).write(true).open(&path) + && let Ok(mut out) = crate::fs::File::options().create(true).append(true).open(&path) { write(&mut out, BacktraceStyle::full()); } diff --git a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs new file mode 100644 index 0000000000000..3a93dfee57f33 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs @@ -0,0 +1,11 @@ +// issue: 114146 + +#![feature(return_position_impl_trait_in_trait)] + +trait Foo { + fn bar<'other: 'a>() -> impl Sized + 'a {} + //~^ ERROR use of undeclared lifetime name `'a` + //~| ERROR use of undeclared lifetime name `'a` +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr new file mode 100644 index 0000000000000..3a1f8f9083747 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr @@ -0,0 +1,33 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/bad-item-bound-within-rpitit-2.rs:6:20 + | +LL | fn bar<'other: 'a>() -> impl Sized + 'a {} + | ^^ undeclared lifetime + | +help: consider introducing lifetime `'a` here + | +LL | fn bar<'a, 'other: 'a>() -> impl Sized + 'a {} + | +++ +help: consider introducing lifetime `'a` here + | +LL | trait Foo<'a> { + | ++++ + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/bad-item-bound-within-rpitit-2.rs:6:42 + | +LL | fn bar<'other: 'a>() -> impl Sized + 'a {} + | ^^ undeclared lifetime + | +help: consider introducing lifetime `'a` here + | +LL | fn bar<'a, 'other: 'a>() -> impl Sized + 'a {} + | +++ +help: consider introducing lifetime `'a` here + | +LL | trait Foo<'a> { + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.rs b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.rs new file mode 100644 index 0000000000000..8b97336fe0c67 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.rs @@ -0,0 +1,25 @@ +// issue: 114145 + +#![feature(return_position_impl_trait_in_trait)] + +trait Iterable { + type Item<'a> + where + Self: 'a; + + fn iter(&self) -> impl '_ + Iterator>; +} + +impl<'a, I: 'a + Iterable> Iterable for &'a I { + type Item<'b> = I::Item<'a> + where + 'b: 'a; + //~^ ERROR impl has stricter requirements than trait + + fn iter(&self) -> impl 'a + Iterator> { + //~^ ERROR the type `&'a I` does not fulfill the required lifetime + (*self).iter() + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr new file mode 100644 index 0000000000000..54a08c5b516c4 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr @@ -0,0 +1,30 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/bad-item-bound-within-rpitit.rs:16:13 + | +LL | type Item<'a> + | ------------- definition of `Item` from trait +... +LL | 'b: 'a; + | ^^ impl has extra requirement `'b: 'a` + | +help: copy the `where` clause predicates from the trait + | +LL | where Self: 'b; + | ~~~~~~~~~~~~~~ + +error[E0477]: the type `&'a I` does not fulfill the required lifetime + --> $DIR/bad-item-bound-within-rpitit.rs:19:23 + | +LL | fn iter(&self) -> impl 'a + Iterator> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: type must outlive the anonymous lifetime as defined here + --> $DIR/bad-item-bound-within-rpitit.rs:10:28 + | +LL | fn iter(&self) -> impl '_ + Iterator>; + | ^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0276, E0477. +For more information about an error, try `rustc --explain E0276`. diff --git a/tests/ui/impl-trait/in-trait/rpitit-shadowed-by-missing-adt.rs b/tests/ui/impl-trait/in-trait/rpitit-shadowed-by-missing-adt.rs new file mode 100644 index 0000000000000..7682884f87931 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/rpitit-shadowed-by-missing-adt.rs @@ -0,0 +1,18 @@ +// issue: 113903 + +#![feature(return_position_impl_trait_in_trait)] + +use std::ops::Deref; + +pub trait Tr { + fn w() -> impl Deref>; + //~^ ERROR cannot find type `Missing` in this scope +} + +impl Tr for () { + fn w() -> &'static () { + &() + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/rpitit-shadowed-by-missing-adt.stderr b/tests/ui/impl-trait/in-trait/rpitit-shadowed-by-missing-adt.stderr new file mode 100644 index 0000000000000..6e4a5bb5df36a --- /dev/null +++ b/tests/ui/impl-trait/in-trait/rpitit-shadowed-by-missing-adt.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `Missing` in this scope + --> $DIR/rpitit-shadowed-by-missing-adt.rs:8:35 + | +LL | fn w() -> impl Deref>; + | ^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/lint/lint-cap-trait-bounds.rs b/tests/ui/lint/lint-cap-trait-bounds.rs new file mode 100644 index 0000000000000..d9c28dd0aa6eb --- /dev/null +++ b/tests/ui/lint/lint-cap-trait-bounds.rs @@ -0,0 +1,8 @@ +// Regression test for https://github.com/rust-lang/rust/issues/43134 + +// check-pass +// compile-flags: --cap-lints allow + +type Foo = Option; + +fn main() {} diff --git a/tests/ui/methods/suggest-method-on-call-with-macro-rcvr.rs b/tests/ui/methods/suggest-method-on-call-with-macro-rcvr.rs new file mode 100644 index 0000000000000..93b7ddf5e9e09 --- /dev/null +++ b/tests/ui/methods/suggest-method-on-call-with-macro-rcvr.rs @@ -0,0 +1,6 @@ +// issue: 114131 + +fn main() { + let hello = len(vec![]); + //~^ ERROR cannot find function `len` in this scope +} diff --git a/tests/ui/methods/suggest-method-on-call-with-macro-rcvr.stderr b/tests/ui/methods/suggest-method-on-call-with-macro-rcvr.stderr new file mode 100644 index 0000000000000..9694f80ab6d0f --- /dev/null +++ b/tests/ui/methods/suggest-method-on-call-with-macro-rcvr.stderr @@ -0,0 +1,15 @@ +error[E0425]: cannot find function `len` in this scope + --> $DIR/suggest-method-on-call-with-macro-rcvr.rs:4:17 + | +LL | let hello = len(vec![]); + | ^^^ not found in this scope + | +help: use the `.` operator to call the method `len` on `&Vec<_>` + | +LL - let hello = len(vec![]); +LL + let hello = vec![].len(); + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/privacy/issue-113860-1.rs b/tests/ui/privacy/issue-113860-1.rs new file mode 100644 index 0000000000000..86ccca41f3795 --- /dev/null +++ b/tests/ui/privacy/issue-113860-1.rs @@ -0,0 +1,16 @@ +#![feature(staged_api)] +//~^ ERROR module has missing stability attribute + +pub trait Trait { + //~^ ERROR trait has missing stability attribute + fn fun() {} + //~^ ERROR associated function has missing stability attribute +} + +impl Trait for u8 { + //~^ ERROR implementation has missing stability attribute + pub(self) fn fun() {} + //~^ ERROR visibility qualifiers are not permitted here [E0449] +} + +fn main() {} diff --git a/tests/ui/privacy/issue-113860-1.stderr b/tests/ui/privacy/issue-113860-1.stderr new file mode 100644 index 0000000000000..c33ce26f0f6e8 --- /dev/null +++ b/tests/ui/privacy/issue-113860-1.stderr @@ -0,0 +1,49 @@ +error[E0449]: visibility qualifiers are not permitted here + --> $DIR/issue-113860-1.rs:12:5 + | +LL | pub(self) fn fun() {} + | ^^^^^^^^^ + | + = note: trait items always share the visibility of their trait + +error: module has missing stability attribute + --> $DIR/issue-113860-1.rs:1:1 + | +LL | / #![feature(staged_api)] +LL | | +LL | | +LL | | pub trait Trait { +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: trait has missing stability attribute + --> $DIR/issue-113860-1.rs:4:1 + | +LL | / pub trait Trait { +LL | | +LL | | fn fun() {} +LL | | +LL | | } + | |_^ + +error: implementation has missing stability attribute + --> $DIR/issue-113860-1.rs:10:1 + | +LL | / impl Trait for u8 { +LL | | +LL | | pub(self) fn fun() {} +LL | | +LL | | } + | |_^ + +error: associated function has missing stability attribute + --> $DIR/issue-113860-1.rs:6:5 + | +LL | fn fun() {} + | ^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0449`. diff --git a/tests/ui/privacy/issue-113860-2.rs b/tests/ui/privacy/issue-113860-2.rs new file mode 100644 index 0000000000000..59be19d88a018 --- /dev/null +++ b/tests/ui/privacy/issue-113860-2.rs @@ -0,0 +1,16 @@ +#![feature(staged_api)] +//~^ ERROR module has missing stability attribute + +pub trait Trait { + //~^ ERROR trait has missing stability attribute + type X; + //~^ ERROR associated type has missing stability attribute +} + +impl Trait for u8 { + //~^ ERROR implementation has missing stability attribute + pub(self) type X = Self; + //~^ ERROR visibility qualifiers are not permitted here [E0449] +} + +fn main() {} diff --git a/tests/ui/privacy/issue-113860-2.stderr b/tests/ui/privacy/issue-113860-2.stderr new file mode 100644 index 0000000000000..6748bc276684a --- /dev/null +++ b/tests/ui/privacy/issue-113860-2.stderr @@ -0,0 +1,49 @@ +error[E0449]: visibility qualifiers are not permitted here + --> $DIR/issue-113860-2.rs:12:5 + | +LL | pub(self) type X = Self; + | ^^^^^^^^^ + | + = note: trait items always share the visibility of their trait + +error: module has missing stability attribute + --> $DIR/issue-113860-2.rs:1:1 + | +LL | / #![feature(staged_api)] +LL | | +LL | | +LL | | pub trait Trait { +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: trait has missing stability attribute + --> $DIR/issue-113860-2.rs:4:1 + | +LL | / pub trait Trait { +LL | | +LL | | type X; +LL | | +LL | | } + | |_^ + +error: implementation has missing stability attribute + --> $DIR/issue-113860-2.rs:10:1 + | +LL | / impl Trait for u8 { +LL | | +LL | | pub(self) type X = Self; +LL | | +LL | | } + | |_^ + +error: associated type has missing stability attribute + --> $DIR/issue-113860-2.rs:6:5 + | +LL | type X; + | ^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0449`. diff --git a/tests/ui/privacy/issue-113860.rs b/tests/ui/privacy/issue-113860.rs new file mode 100644 index 0000000000000..b94c14fac4e1c --- /dev/null +++ b/tests/ui/privacy/issue-113860.rs @@ -0,0 +1,16 @@ +#![feature(staged_api)] +//~^ ERROR module has missing stability attribute + +pub trait Trait { + //~^ ERROR trait has missing stability attribute + const X: u32; + //~^ ERROR associated constant has missing stability attribute +} + +impl Trait for u8 { + //~^ ERROR implementation has missing stability attribute + pub(self) const X: u32 = 3; + //~^ ERROR visibility qualifiers are not permitted here [E0449] +} + +fn main() {} diff --git a/tests/ui/privacy/issue-113860.stderr b/tests/ui/privacy/issue-113860.stderr new file mode 100644 index 0000000000000..3204f4ff9162f --- /dev/null +++ b/tests/ui/privacy/issue-113860.stderr @@ -0,0 +1,49 @@ +error[E0449]: visibility qualifiers are not permitted here + --> $DIR/issue-113860.rs:12:5 + | +LL | pub(self) const X: u32 = 3; + | ^^^^^^^^^ + | + = note: trait items always share the visibility of their trait + +error: module has missing stability attribute + --> $DIR/issue-113860.rs:1:1 + | +LL | / #![feature(staged_api)] +LL | | +LL | | +LL | | pub trait Trait { +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: trait has missing stability attribute + --> $DIR/issue-113860.rs:4:1 + | +LL | / pub trait Trait { +LL | | +LL | | const X: u32; +LL | | +LL | | } + | |_^ + +error: implementation has missing stability attribute + --> $DIR/issue-113860.rs:10:1 + | +LL | / impl Trait for u8 { +LL | | +LL | | pub(self) const X: u32 = 3; +LL | | +LL | | } + | |_^ + +error: associated constant has missing stability attribute + --> $DIR/issue-113860.rs:6:5 + | +LL | const X: u32; + | ^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0449`.