Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge check_mod_impl_wf and check_mod_type_wf #121154

Merged
merged 1 commit into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,8 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
let header = tcx.impl_trait_header(def_id);
let is_auto = header
.is_some_and(|header| tcx.trait_is_auto(header.skip_binder().trait_ref.def_id));

crate::impl_wf_check::check_impl_wf(tcx, def_id)?;
let mut res = Ok(());
if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) {
let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span);
Expand Down
22 changes: 7 additions & 15 deletions compiler/rustc_hir_analysis/src/impl_wf_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ use min_specialization::check_min_specialization;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{codes::*, struct_span_code_err};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{LocalDefId, LocalModDefId};
use rustc_middle::query::Providers;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
use rustc_span::{ErrorGuaranteed, Span, Symbol};

Expand Down Expand Up @@ -51,23 +50,16 @@ mod min_specialization;
/// impl<'a> Trait<Foo> for Bar { type X = &'a i32; }
/// // ^ 'a is unused and appears in assoc type, error
/// ```
fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) -> Result<(), ErrorGuaranteed> {
pub fn check_impl_wf(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
let min_specialization = tcx.features().min_specialization;
let module = tcx.hir_module_items(module_def_id);
let mut res = Ok(());
for id in module.items() {
if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. }) {
res = res.and(enforce_impl_params_are_constrained(tcx, id.owner_id.def_id));
if min_specialization {
res = res.and(check_min_specialization(tcx, id.owner_id.def_id));
}
}
debug_assert!(matches!(tcx.def_kind(impl_def_id), DefKind::Impl { .. }));
res = res.and(enforce_impl_params_are_constrained(tcx, impl_def_id));
if min_specialization {
res = res.and(check_min_specialization(tcx, impl_def_id));
}
res
}

pub fn provide(providers: &mut Providers) {
*providers = Providers { check_mod_impl_wf, ..*providers };
res
}

fn enforce_impl_params_are_constrained(
Expand Down
16 changes: 4 additions & 12 deletions compiler/rustc_hir_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,6 @@ pub fn provide(providers: &mut Providers) {
check_unused::provide(providers);
variance::provide(providers);
outlives::provide(providers);
impl_wf_check::provide(providers);
hir_wf_check::provide(providers);
}

Expand All @@ -171,29 +170,22 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
}

tcx.sess.time("coherence_checking", || {
// Check impls constrain their parameters
let res =
tcx.hir().try_par_for_each_module(|module| tcx.ensure().check_mod_impl_wf(module));
tcx.hir().par_for_each_module(|module| {
let _ = tcx.ensure().check_mod_type_wf(module);
});

for &trait_def_id in tcx.all_local_trait_impls(()).keys() {
let _ = tcx.ensure().coherent_trait(trait_def_id);
}
// these queries are executed for side-effects (error reporting):
let _ = tcx.ensure().crate_inherent_impls(());
let _ = tcx.ensure().crate_inherent_impls_overlap_check(());
res
})?;
});
Comment on lines -174 to +183
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just removing this early abort causes annoying diagnostics that are hard to make good. So what I did instead was to inline the check_mod_impl_wf checks directly into the individual check_well_formed of impl items and early abort per item. So that only items with errors in impl_wf checks don't get their type_wf run, but other items do


if tcx.features().rustc_attrs {
tcx.sess.time("variance_testing", || variance::test::test_variance(tcx))?;
}

tcx.sess.time("wf_checking", || {
tcx.hir().par_for_each_module(|module| {
let _ = tcx.ensure().check_mod_type_wf(module);
})
});

if tcx.features().rustc_attrs {
collect::test_opaque_hidden_types(tcx)?;
}
Expand Down
5 changes: 0 additions & 5 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -955,11 +955,6 @@ rustc_queries! {
desc { |tcx| "checking deathness of variables in {}", describe_as_module(key, tcx) }
}

query check_mod_impl_wf(key: LocalModDefId) -> Result<(), ErrorGuaranteed> {
desc { |tcx| "checking that impls are well-formed in {}", describe_as_module(key, tcx) }
ensure_forwards_result_if_red
}

query check_mod_type_wf(key: LocalModDefId) -> Result<(), ErrorGuaranteed> {
desc { |tcx| "checking that types are well-formed in {}", describe_as_module(key, tcx) }
ensure_forwards_result_if_red
Expand Down
17 changes: 13 additions & 4 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2593,10 +2593,19 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
let span = *entry.get();
let err = ResolutionError::NameAlreadyUsedInParameterList(ident.name, span);
self.report_error(param.ident.span, err);
if let GenericParamKind::Lifetime = param.kind {
// Record lifetime res, so lowering knows there is something fishy.
self.record_lifetime_param(param.id, LifetimeRes::Error);
}
let rib = match param.kind {
GenericParamKind::Lifetime => {
// Record lifetime res, so lowering knows there is something fishy.
self.record_lifetime_param(param.id, LifetimeRes::Error);
continue;
}
GenericParamKind::Type { .. } => &mut function_type_rib,
GenericParamKind::Const { .. } => &mut function_value_rib,
};

// Taint the resolution in case of errors to prevent follow up errors in typeck
self.r.record_partial_res(param.id, PartialRes::new(Res::Err));
rib.bindings.insert(ident, Res::Err);
continue;
}
Entry::Vacant(entry) => {
Expand Down
9 changes: 8 additions & 1 deletion compiler/rustc_traits/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::{FulfillmentErrorCode, TraitEngineExt as _};
use rustc_middle::traits::CodegenObligationError;
use rustc_middle::ty::{self, TyCtxt};
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
use rustc_trait_selection::traits::{
ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine, TraitEngineExt,
Expand Down Expand Up @@ -72,6 +72,13 @@ pub fn codegen_select_candidate<'tcx>(

let impl_source = infcx.resolve_vars_if_possible(impl_source);
let impl_source = infcx.tcx.erase_regions(impl_source);
if impl_source.has_infer() {
// Unused lifetimes on an impl get replaced with inference vars, but never resolved,
// causing the return value of a query to contain inference vars. We do not have a concept
// for this and will in fact ICE in stable hashing of the return value. So bail out instead.
infcx.tcx.dcx().has_errors().unwrap();
return Err(CodegenObligationError::FulfillmentError);
}

Ok(&*tcx.arena.alloc(impl_source))
}
2 changes: 1 addition & 1 deletion tests/rustdoc-ui/not-wf-ambiguous-normalization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ struct DefaultAllocator;
// `<DefaultAllocator as Allocator>::Buffer` to be ambiguous,
// which caused an ICE with `-Znormalize-docs`.
impl<T> Allocator for DefaultAllocator {
//~^ ERROR: type annotations needed
//~^ ERROR: the type parameter `T` is not constrained
type Buffer = ();
}

Expand Down
8 changes: 4 additions & 4 deletions tests/rustdoc-ui/not-wf-ambiguous-normalization.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
error[E0282]: type annotations needed
--> $DIR/not-wf-ambiguous-normalization.rs:14:23
error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
--> $DIR/not-wf-ambiguous-normalization.rs:14:6
|
LL | impl<T> Allocator for DefaultAllocator {
| ^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T`
| ^ unconstrained type parameter

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0282`.
For more information about this error, try `rustc --explain E0207`.
38 changes: 19 additions & 19 deletions tests/ui/associated-types/issue-38821.stderr
Original file line number Diff line number Diff line change
@@ -1,22 +1,3 @@
error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied
--> $DIR/issue-38821.rs:23:17
|
LL | #[derive(Debug, Copy, Clone)]
| ^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`, which is required by `<Col as Expression>::SqlType: IntoNullable`
|
note: required for `<Col as Expression>::SqlType` to implement `IntoNullable`
--> $DIR/issue-38821.rs:9:18
|
LL | impl<T: NotNull> IntoNullable for T {
| ------- ^^^^^^^^^^^^ ^
| |
| unsatisfied trait bound introduced here
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider further restricting the associated type
|
LL | Expr: Expression<SqlType=<Col::SqlType as IntoNullable>::Nullable>, <Col as Expression>::SqlType: NotNull,
| +++++++++++++++++++++++++++++++++++++++

error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied
--> $DIR/issue-38821.rs:40:1
|
Expand Down Expand Up @@ -129,6 +110,25 @@ LL | impl<T: NotNull> IntoNullable for T {
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
= note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied
--> $DIR/issue-38821.rs:23:17
|
LL | #[derive(Debug, Copy, Clone)]
| ^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`, which is required by `<Col as Expression>::SqlType: IntoNullable`
|
note: required for `<Col as Expression>::SqlType` to implement `IntoNullable`
--> $DIR/issue-38821.rs:9:18
|
LL | impl<T: NotNull> IntoNullable for T {
| ------- ^^^^^^^^^^^^ ^
| |
| unsatisfied trait bound introduced here
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider further restricting the associated type
|
LL | Expr: Expression<SqlType=<Col::SqlType as IntoNullable>::Nullable>, <Col as Expression>::SqlType: NotNull,
| +++++++++++++++++++++++++++++++++++++++

error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied
--> $DIR/issue-38821.rs:23:17
|
Expand Down
22 changes: 11 additions & 11 deletions tests/ui/coherence/coherence-orphan.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,6 @@ LL | impl TheTrait<usize> for isize {}
|
= note: define and implement a trait or new type instead

error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
--> $DIR/coherence-orphan.rs:20:1
|
LL | impl !Send for Vec<isize> {}
| ^^^^^^^^^^^^^^^----------
| | |
| | `Vec` is not defined in the current crate
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead

error[E0046]: not all trait items implemented, missing: `the_fn`
--> $DIR/coherence-orphan.rs:10:1
|
Expand All @@ -45,6 +34,17 @@ LL | impl TheTrait<isize> for TheType {}
|
= help: implement the missing item: `fn the_fn(&self) { todo!() }`

error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
--> $DIR/coherence-orphan.rs:20:1
|
LL | impl !Send for Vec<isize> {}
| ^^^^^^^^^^^^^^^----------
| | |
| | `Vec` is not defined in the current crate
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead

error: aborting due to 5 previous errors

Some errors have detailed explanations: E0046, E0117.
Expand Down
26 changes: 23 additions & 3 deletions tests/ui/const-generics/issues/issue-68366.full.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
error: `Option<usize>` is forbidden as the type of a const generic parameter
--> $DIR/issue-68366.rs:9:25
|
LL | struct Collatz<const N: Option<usize>>;
| ^^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types

error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates
--> $DIR/issue-68366.rs:11:7
--> $DIR/issue-68366.rs:12:7
|
LL | impl <const N: usize> Collatz<{Some(N)}> {}
| ^^^^^^^^^^^^^^ unconstrained const parameter
Expand All @@ -8,14 +17,25 @@ LL | impl <const N: usize> Collatz<{Some(N)}> {}
= note: proving the result of expressions other than the parameter are unique is not supported

error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates
--> $DIR/issue-68366.rs:17:6
--> $DIR/issue-68366.rs:19:6
|
LL | impl<const N: usize> Foo {}
| ^^^^^^^^^^^^^^ unconstrained const parameter
|
= note: expressions using a const parameter must map each value to a distinct output value
= note: proving the result of expressions other than the parameter are unique is not supported

error: aborting due to 2 previous errors
error: overly complex generic constant
--> $DIR/issue-68366.rs:12:31
|
LL | impl <const N: usize> Collatz<{Some(N)}> {}
| ^-------^
| |
| struct/enum construction is not supported in generic constants
|
= help: consider moving this anonymous constant into a `const` function
= note: this operation may be supported in the future

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0207`.
17 changes: 13 additions & 4 deletions tests/ui/const-generics/issues/issue-68366.min.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
error: generic parameters may not be used in const operations
--> $DIR/issue-68366.rs:11:37
--> $DIR/issue-68366.rs:12:37
|
LL | impl <const N: usize> Collatz<{Some(N)}> {}
| ^ cannot perform const operation using `N`
|
= help: const parameters may only be used as standalone arguments, i.e. `N`
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions

error: `Option<usize>` is forbidden as the type of a const generic parameter
--> $DIR/issue-68366.rs:9:25
|
LL | struct Collatz<const N: Option<usize>>;
| ^^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types

error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates
--> $DIR/issue-68366.rs:11:7
--> $DIR/issue-68366.rs:12:7
|
LL | impl <const N: usize> Collatz<{Some(N)}> {}
| ^^^^^^^^^^^^^^ unconstrained const parameter
Expand All @@ -17,14 +26,14 @@ LL | impl <const N: usize> Collatz<{Some(N)}> {}
= note: proving the result of expressions other than the parameter are unique is not supported

error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates
--> $DIR/issue-68366.rs:17:6
--> $DIR/issue-68366.rs:19:6
|
LL | impl<const N: usize> Foo {}
| ^^^^^^^^^^^^^^ unconstrained const parameter
|
= note: expressions using a const parameter must map each value to a distinct output value
= note: proving the result of expressions other than the parameter are unique is not supported

error: aborting due to 3 previous errors
error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0207`.
2 changes: 2 additions & 0 deletions tests/ui/const-generics/issues/issue-68366.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
#![cfg_attr(full, allow(incomplete_features))]

struct Collatz<const N: Option<usize>>;
//~^ ERROR: `Option<usize>` is forbidden

impl <const N: usize> Collatz<{Some(N)}> {}
//~^ ERROR the const parameter
//[min]~^^ generic parameters may not be used in const operations
//[full]~^^^ ERROR overly complex

struct Foo;

Expand Down
1 change: 0 additions & 1 deletion tests/ui/duplicate/duplicate-type-parameter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ trait Qux<T,T> {}

impl<T,T> Qux<T,T> for Option<T> {}
//~^ ERROR the name `T` is already used
//~^^ ERROR the type parameter `T` is not constrained

fn main() {
}
11 changes: 2 additions & 9 deletions tests/ui/duplicate/duplicate-type-parameter.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,6 @@ LL | impl<T,T> Qux<T,T> for Option<T> {}
| |
| first use of `T`

error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
--> $DIR/duplicate-type-parameter.rs:24:8
|
LL | impl<T,T> Qux<T,T> for Option<T> {}
| ^ unconstrained type parameter

error: aborting due to 8 previous errors
error: aborting due to 7 previous errors

Some errors have detailed explanations: E0207, E0403.
For more information about an error, try `rustc --explain E0207`.
For more information about this error, try `rustc --explain E0403`.
Loading
Loading