diff --git a/Cargo.toml b/Cargo.toml index 0391507883861..2ea16c2266615 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,7 +64,7 @@ exclude = [ ] [profile.release.package.compiler_builtins] -# The compiler-builtins crate cannot reference libcore, and it's own CI will +# The compiler-builtins crate cannot reference libcore, and its own CI will # verify that this is the case. This requires, however, that the crate is built # without overflow checks and debug assertions. Forcefully disable debug # assertions and overflow checks here which should ensure that even if these diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index aa0db9891a5ad..6e3996b45099e 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -77,7 +77,7 @@ declare_features! ( /// Allows empty structs and enum variants with braces. (accepted, braced_empty_structs, "1.8.0", Some(29720)), /// Allows `c"foo"` literals. - (accepted, c_str_literals, "1.76.0", Some(105723)), + (accepted, c_str_literals, "CURRENT_RUSTC_VERSION", Some(105723)), /// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`. (accepted, cfg_attr_multi, "1.33.0", Some(54881)), /// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests. diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 59ea828440f5b..2f2b551e6ecf7 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -450,7 +450,7 @@ declare_features! ( (unstable, doc_masked, "1.21.0", Some(44027)), /// Allows `dyn* Trait` objects. (incomplete, dyn_star, "1.65.0", Some(102425)), - // Uses generic effect parameters for ~const bounds + /// Uses generic effect parameters for ~const bounds (unstable, effects, "1.72.0", Some(102090)), /// Allows `X..Y` patterns. (unstable, exclusive_range_pattern, "1.11.0", Some(37854)), diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 0ab09dadf585d..8a4fd01437f91 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -113,6 +113,7 @@ macro_rules! arena_types { [] stripped_cfg_items: rustc_ast::expand::StrippedCfgItem, [] mod_child: rustc_middle::metadata::ModChild, [] features: rustc_feature::Features, + [decode] specialization_graph: rustc_middle::traits::specialization_graph::Graph, ]); ) } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 0e3b9984423f8..1dc7722088108 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1294,8 +1294,7 @@ rustc_queries! { desc { |tcx| "finding trait impls of `{}`", tcx.def_path_str(trait_id) } } - query specialization_graph_of(trait_id: DefId) -> &'tcx specialization_graph::Graph { - arena_cache + query specialization_graph_of(trait_id: DefId) -> Result<&'tcx specialization_graph::Graph, ErrorGuaranteed> { desc { |tcx| "building specialization graph of trait `{}`", tcx.def_path_str(trait_id) } cache_on_disk_if { true } } diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 31db4ba62fb4f..f4dfbe059ebcd 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -786,6 +786,15 @@ impl<'a, 'tcx> Decodable> for &'tcx [rustc_ast::InlineAsm } } +impl<'a, 'tcx> Decodable> + for &'tcx crate::traits::specialization_graph::Graph +{ + #[inline] + fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self { + RefDecodable::decode(d) + } +} + macro_rules! impl_ref_decoder { (<$tcx:tt> $($ty:ty,)*) => { $(impl<'a, $tcx> Decodable> for &$tcx [$ty] { diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs index 898258445dc85..ba29d4040a1e7 100644 --- a/compiler/rustc_middle/src/traits/specialization_graph.rs +++ b/compiler/rustc_middle/src/traits/specialization_graph.rs @@ -30,18 +30,16 @@ pub struct Graph { /// The "root" impls are found by looking up the trait's def_id. pub children: DefIdMap, - - /// Whether an error was emitted while constructing the graph. - pub has_errored: Option, } impl Graph { pub fn new() -> Graph { - Graph { parent: Default::default(), children: Default::default(), has_errored: None } + Graph { parent: Default::default(), children: Default::default() } } /// The parent of a given impl, which is the `DefId` of the trait when the /// impl is a "specialization root". + #[track_caller] pub fn parent(&self, child: DefId) -> DefId { *self.parent.get(&child).unwrap_or_else(|| panic!("Failed to get parent for {child:?}")) } @@ -255,13 +253,9 @@ pub fn ancestors( trait_def_id: DefId, start_from_impl: DefId, ) -> Result, ErrorGuaranteed> { - let specialization_graph = tcx.specialization_graph_of(trait_def_id); + let specialization_graph = tcx.specialization_graph_of(trait_def_id)?; - if let Some(reported) = specialization_graph.has_errored { - Err(reported) - } else if let Err(reported) = - tcx.type_of(start_from_impl).instantiate_identity().error_reported() - { + if let Err(reported) = tcx.type_of(start_from_impl).instantiate_identity().error_reported() { Err(reported) } else { Ok(Ancestors { diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 6ed68f90eb38e..b71919adc58fa 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -32,6 +32,7 @@ pub enum SimplifiedType { CoroutineWitness(DefId), Function(usize), Placeholder, + Error, } /// Generic parameters are pretty much just bound variables, e.g. @@ -153,7 +154,8 @@ pub fn simplify_type<'tcx>( TreatParams::ForLookup | TreatParams::AsCandidateKey => None, }, ty::Foreign(def_id) => Some(SimplifiedType::Foreign(def_id)), - ty::Bound(..) | ty::Infer(_) | ty::Error(_) => None, + ty::Error(_) => Some(SimplifiedType::Error), + ty::Bound(..) | ty::Infer(_) => None, } } diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index bf9b244936fc6..227a0753d0429 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -1,6 +1,5 @@ use crate::traits::specialization_graph; use crate::ty::fast_reject::{self, SimplifiedType, TreatParams, TreatProjections}; -use crate::ty::visit::TypeVisitableExt; use crate::ty::{Ident, Ty, TyCtxt}; use hir::def_id::LOCAL_CRATE; use rustc_hir as hir; @@ -241,9 +240,6 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait let impl_def_id = impl_def_id.to_def_id(); let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity(); - if impl_self_ty.references_error() { - continue; - } if let Some(simplified_self_ty) = fast_reject::simplify_type(tcx, impl_self_ty, TreatParams::AsCandidateKey) diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 10329c623b386..200d022c80c69 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -26,7 +26,7 @@ use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{GenericArgs, GenericArgsRef}; use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK; use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP}; use super::util; use super::SelectionContext; @@ -258,7 +258,7 @@ fn fulfill_implication<'tcx>( pub(super) fn specialization_graph_provider( tcx: TyCtxt<'_>, trait_id: DefId, -) -> specialization_graph::Graph { +) -> Result<&'_ specialization_graph::Graph, ErrorGuaranteed> { let mut sg = specialization_graph::Graph::new(); let overlap_mode = specialization_graph::OverlapMode::get(tcx, trait_id); @@ -271,6 +271,8 @@ pub(super) fn specialization_graph_provider( trait_impls .sort_unstable_by_key(|def_id| (-(def_id.krate.as_u32() as i64), def_id.index.index())); + let mut errored = Ok(()); + for impl_def_id in trait_impls { if let Some(impl_def_id) = impl_def_id.as_local() { // This is where impl overlap checking happens: @@ -283,15 +285,21 @@ pub(super) fn specialization_graph_provider( }; if let Some(overlap) = overlap { - report_overlap_conflict(tcx, overlap, impl_def_id, used_to_be_allowed, &mut sg); + errored = errored.and(report_overlap_conflict( + tcx, + overlap, + impl_def_id, + used_to_be_allowed, + )); } } else { let parent = tcx.impl_parent(impl_def_id).unwrap_or(trait_id); sg.record_impl_from_cstore(tcx, parent, impl_def_id) } } + errored?; - sg + Ok(tcx.arena.alloc(sg)) } // This function is only used when @@ -304,36 +312,31 @@ fn report_overlap_conflict<'tcx>( overlap: OverlapError<'tcx>, impl_def_id: LocalDefId, used_to_be_allowed: Option, - sg: &mut specialization_graph::Graph, -) { +) -> Result<(), ErrorGuaranteed> { let impl_polarity = tcx.impl_polarity(impl_def_id.to_def_id()); let other_polarity = tcx.impl_polarity(overlap.with_impl); match (impl_polarity, other_polarity) { (ty::ImplPolarity::Negative, ty::ImplPolarity::Positive) => { - report_negative_positive_conflict( + Err(report_negative_positive_conflict( tcx, &overlap, impl_def_id, impl_def_id.to_def_id(), overlap.with_impl, - sg, - ); + )) } (ty::ImplPolarity::Positive, ty::ImplPolarity::Negative) => { - report_negative_positive_conflict( + Err(report_negative_positive_conflict( tcx, &overlap, impl_def_id, overlap.with_impl, impl_def_id.to_def_id(), - sg, - ); + )) } - _ => { - report_conflicting_impls(tcx, overlap, impl_def_id, used_to_be_allowed, sg); - } + _ => report_conflicting_impls(tcx, overlap, impl_def_id, used_to_be_allowed), } } @@ -343,16 +346,16 @@ fn report_negative_positive_conflict<'tcx>( local_impl_def_id: LocalDefId, negative_impl_def_id: DefId, positive_impl_def_id: DefId, - sg: &mut specialization_graph::Graph, -) { - let err = tcx.dcx().create_err(NegativePositiveConflict { - impl_span: tcx.def_span(local_impl_def_id), - trait_desc: overlap.trait_ref, - self_ty: overlap.self_ty, - negative_impl_span: tcx.span_of_impl(negative_impl_def_id), - positive_impl_span: tcx.span_of_impl(positive_impl_def_id), - }); - sg.has_errored = Some(err.emit()); +) -> ErrorGuaranteed { + tcx.dcx() + .create_err(NegativePositiveConflict { + impl_span: tcx.def_span(local_impl_def_id), + trait_desc: overlap.trait_ref, + self_ty: overlap.self_ty, + negative_impl_span: tcx.span_of_impl(negative_impl_def_id), + positive_impl_span: tcx.span_of_impl(positive_impl_def_id), + }) + .emit() } fn report_conflicting_impls<'tcx>( @@ -360,8 +363,7 @@ fn report_conflicting_impls<'tcx>( overlap: OverlapError<'tcx>, impl_def_id: LocalDefId, used_to_be_allowed: Option, - sg: &mut specialization_graph::Graph, -) { +) -> Result<(), ErrorGuaranteed> { let impl_span = tcx.def_span(impl_def_id); // Work to be done after we've built the DiagnosticBuilder. We have to define it @@ -429,14 +431,11 @@ fn report_conflicting_impls<'tcx>( let mut err = tcx.dcx().struct_span_err(impl_span, msg); err.code(error_code!(E0119)); decorate(tcx, &overlap, impl_span, &mut err); - Some(err.emit()) + err.emit() } else { - Some( - tcx.dcx() - .span_delayed_bug(impl_span, "impl should have failed the orphan check"), - ) + tcx.dcx().span_delayed_bug(impl_span, "impl should have failed the orphan check") }; - sg.has_errored = reported; + Err(reported) } Some(kind) => { let lint = match kind { @@ -452,8 +451,9 @@ fn report_conflicting_impls<'tcx>( decorate(tcx, &overlap, impl_span, err); }, ); + Ok(()) } - }; + } } /// Recovers the "impl X for Y" signature from `impl_def_id` and returns it as a diff --git a/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.rs b/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.rs new file mode 100644 index 0000000000000..cd3acf9bc41b1 --- /dev/null +++ b/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.rs @@ -0,0 +1,16 @@ +trait Foo { + type Context<'c> + where + Self: 'c; +} + +impl Foo for Box {} +//~^ ERROR `Foo` cannot be made into an object +//~| ERROR `Foo` cannot be made into an object +//~| ERROR cycle detected +//~| ERROR cycle detected +//~| ERROR cycle detected +//~| ERROR the trait bound `Box<(dyn Foo + 'static)>: Foo` is not satisfied +//~| ERROR not all trait items implemented + +fn main() {} diff --git a/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.stderr b/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.stderr new file mode 100644 index 0000000000000..8e6b69f7461d9 --- /dev/null +++ b/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.stderr @@ -0,0 +1,119 @@ +error[E0391]: cycle detected when computing type of `` + --> $DIR/unknown-lifetime-ice-119827.rs:7:1 + | +LL | impl Foo for Box {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires finding trait impls of `Foo`... + --> $DIR/unknown-lifetime-ice-119827.rs:1:1 + | +LL | trait Foo { + | ^^^^^^^^^ + = note: ...which again requires computing type of ``, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/unknown-lifetime-ice-119827.rs:1:1 + | +LL | / trait Foo { +LL | | type Context<'c> +LL | | where +LL | | Self: 'c; +... | +LL | | +LL | | fn main() {} + | |____________^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error[E0391]: cycle detected when computing type of `` + --> $DIR/unknown-lifetime-ice-119827.rs:7:1 + | +LL | impl Foo for Box {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: ...which immediately requires computing type of `` again +note: cycle used when collecting item types in top-level module + --> $DIR/unknown-lifetime-ice-119827.rs:1:1 + | +LL | / trait Foo { +LL | | type Context<'c> +LL | | where +LL | | Self: 'c; +... | +LL | | +LL | | fn main() {} + | |____________^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error[E0391]: cycle detected when computing type of `` + --> $DIR/unknown-lifetime-ice-119827.rs:7:1 + | +LL | impl Foo for Box {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: ...which immediately requires computing type of `` again +note: cycle used when collecting item types in top-level module + --> $DIR/unknown-lifetime-ice-119827.rs:1:1 + | +LL | / trait Foo { +LL | | type Context<'c> +LL | | where +LL | | Self: 'c; +... | +LL | | +LL | | fn main() {} + | |____________^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/unknown-lifetime-ice-119827.rs:7:22 + | +LL | impl Foo for Box {} + | ^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/unknown-lifetime-ice-119827.rs:2:10 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | type Context<'c> + | ^^^^^^^ ...because it contains the generic associated type `Context` + = help: consider moving `Context` to another trait + = help: only type `{type error}` implements the trait, consider using it directly instead + +error[E0277]: the trait bound `Box<(dyn Foo + 'static)>: Foo` is not satisfied + --> $DIR/unknown-lifetime-ice-119827.rs:7:14 + | +LL | impl Foo for Box {} + | ^^^^^^^^^^^^ the trait `Foo` is not implemented for `Box<(dyn Foo + 'static)>` + | + = help: the trait `Foo` is implemented for `Box<(dyn Foo + 'static)>` + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/unknown-lifetime-ice-119827.rs:7:14 + | +LL | impl Foo for Box {} + | ^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/unknown-lifetime-ice-119827.rs:2:10 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | type Context<'c> + | ^^^^^^^ ...because it contains the generic associated type `Context` + = help: consider moving `Context` to another trait + = help: only type `std::boxed::Box<(dyn Foo + 'static)>` implements the trait, consider using it directly instead + +error[E0046]: not all trait items implemented, missing: `Context` + --> $DIR/unknown-lifetime-ice-119827.rs:7:1 + | +LL | type Context<'c> + | ---------------- `Context` from trait +... +LL | impl Foo for Box {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Context` in implementation + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0038, E0046, E0277, E0391. +For more information about an error, try `rustc --explain E0038`.