Skip to content

Commit

Permalink
Auto merge of #116885 - aliemjay:rollup-plbeppt, r=aliemjay
Browse files Browse the repository at this point in the history
Rollup of 5 pull requests

Successful merges:

 - #116812 (Disable missing_copy_implementations lint on non_exhaustive types)
 - #116856 (Disable effects in libcore again)
 - #116865 (Suggest constraining assoc types in more cases)
 - #116870 (Don't compare host param by name)
 - #116879 (revert #114586)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Oct 18, 2023
2 parents e8b8c78 + 8489bce commit e1de04a
Show file tree
Hide file tree
Showing 21 changed files with 272 additions and 140 deletions.
33 changes: 13 additions & 20 deletions compiler/rustc_borrowck/src/region_infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,26 +328,19 @@ fn check_opaque_type_well_formed<'tcx>(

// Require that the hidden type actually fulfills all the bounds of the opaque type, even without
// the bounds that the function supplies.
let mut obligations = vec![];
infcx
.insert_hidden_type(
OpaqueTypeKey { def_id, args: identity_args },
&ObligationCause::misc(definition_span, def_id),
param_env,
definition_ty,
true,
&mut obligations,
)
.unwrap();
infcx.add_item_bounds_for_hidden_type(
def_id.to_def_id(),
identity_args,
ObligationCause::misc(definition_span, def_id),
param_env,
definition_ty,
&mut obligations,
);
ocx.register_obligations(obligations);
let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), identity_args);
ocx.eq(&ObligationCause::misc(definition_span, def_id), param_env, opaque_ty, definition_ty)
.map_err(|err| {
infcx
.err_ctxt()
.report_mismatched_types(
&ObligationCause::misc(definition_span, def_id),
opaque_ty,
definition_ty,
err,
)
.emit()
})?;

// Require the hidden type to be well-formed with only the generics of the opaque type.
// Defining use functions may have more bounds than the opaque type, which is ok, as long as the
Expand Down
9 changes: 5 additions & 4 deletions compiler/rustc_hir_analysis/src/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,11 @@ impl<'tcx> Bounds<'tcx> {
) {
self.push_trait_bound_inner(tcx, trait_ref, span, polarity);

// if we have a host param, we push an unconst trait bound in addition
// to the const one.
// FIXME(effects) we should find a better way than name matching
if tcx.features().effects && trait_ref.skip_binder().args.host_effect_param().is_some() {
// push a non-const (`host = true`) version of the bound if it is `~const`.
if tcx.features().effects
&& let Some(host_effect_idx) = tcx.generics_of(trait_ref.def_id()).host_effect_index
&& trait_ref.skip_binder().args.const_at(host_effect_idx) != tcx.consts.true_
{
let generics = tcx.generics_of(trait_ref.def_id());
let Some(host_index) = generics.host_effect_index else { return };
let trait_ref = trait_ref.map_bound(|mut trait_ref| {
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_hir_typeck/src/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -786,8 +786,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
tcx.consts.false_
}
Some(hir::ConstContext::ConstFn) => {
let args = ty::GenericArgs::identity_for_item(tcx, context);
args.host_effect_param().expect("ConstContext::Maybe must have host effect param")
let host_idx = tcx
.generics_of(context)
.host_effect_index
.expect("ConstContext::Maybe must have host effect param");
ty::GenericArgs::identity_for_item(tcx, context).const_at(host_idx)
}
None => tcx.consts.true_,
};
Expand Down
102 changes: 58 additions & 44 deletions compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,39 +341,48 @@ impl<T> Trait<T> for X {
let tcx = self.tcx;
let assoc = tcx.associated_item(proj_ty.def_id);
let (trait_ref, assoc_args) = proj_ty.trait_ref_and_own_args(tcx);
if let Some(item) = tcx.hir().get_if_local(body_owner_def_id) {
if let Some(hir_generics) = item.generics() {
// Get the `DefId` for the type parameter corresponding to `A` in `<A as T>::Foo`.
// This will also work for `impl Trait`.
let def_id = if let ty::Param(param_ty) = proj_ty.self_ty().kind() {
let generics = tcx.generics_of(body_owner_def_id);
generics.type_param(param_ty, tcx).def_id
} else {
return false;
};
let Some(def_id) = def_id.as_local() else {
return false;
};

// First look in the `where` clause, as this might be
// `fn foo<T>(x: T) where T: Trait`.
for pred in hir_generics.bounds_for_param(def_id) {
if self.constrain_generic_bound_associated_type_structured_suggestion(
diag,
&trait_ref,
pred.bounds,
assoc,
assoc_args,
ty,
&msg,
false,
) {
return true;
}
}
let Some(item) = tcx.hir().get_if_local(body_owner_def_id) else {
return false;
};
let Some(hir_generics) = item.generics() else {
return false;
};
// Get the `DefId` for the type parameter corresponding to `A` in `<A as T>::Foo`.
// This will also work for `impl Trait`.
let def_id = if let ty::Param(param_ty) = proj_ty.self_ty().kind() {
let generics = tcx.generics_of(body_owner_def_id);
generics.type_param(param_ty, tcx).def_id
} else {
return false;
};
let Some(def_id) = def_id.as_local() else {
return false;
};

// First look in the `where` clause, as this might be
// `fn foo<T>(x: T) where T: Trait`.
for pred in hir_generics.bounds_for_param(def_id) {
if self.constrain_generic_bound_associated_type_structured_suggestion(
diag,
&trait_ref,
pred.bounds,
assoc,
assoc_args,
ty,
&msg,
false,
) {
return true;
}
}
false
// If associated item, look to constrain the params of the trait/impl.
let hir_id = match item {
hir::Node::ImplItem(item) => item.hir_id(),
hir::Node::TraitItem(item) => item.hir_id(),
_ => return false,
};
let parent = tcx.hir().get_parent_item(hir_id).def_id;
self.suggest_constraint(diag, msg, parent.into(), proj_ty, ty)
}

/// An associated type was expected and a different type was found.
Expand Down Expand Up @@ -426,21 +435,26 @@ impl<T> Trait<T> for X {
let impl_comparison =
matches!(cause_code, ObligationCauseCode::CompareImplItemObligation { .. });
let assoc = tcx.associated_item(proj_ty.def_id);
if !callable_scope || impl_comparison {
if impl_comparison {
// We do not want to suggest calling functions when the reason of the
// type error is a comparison of an `impl` with its `trait` or when the
// scope is outside of a `Body`.
// type error is a comparison of an `impl` with its `trait`.
} else {
// If we find a suitable associated function that returns the expected type, we don't
// want the more general suggestion later in this method about "consider constraining
// the associated type or calling a method that returns the associated type".
let point_at_assoc_fn = self.point_at_methods_that_satisfy_associated_type(
diag,
assoc.container_id(tcx),
current_method_ident,
proj_ty.def_id,
values.expected,
);
let point_at_assoc_fn = if callable_scope
&& self.point_at_methods_that_satisfy_associated_type(
diag,
assoc.container_id(tcx),
current_method_ident,
proj_ty.def_id,
values.expected,
) {
// If we find a suitable associated function that returns the expected type, we
// don't want the more general suggestion later in this method about "consider
// constraining the associated type or calling a method that returns the associated
// type".
true
} else {
false
};
// Possibly suggest constraining the associated type to conform to the
// found type.
if self.suggest_constraint(diag, &msg, body_owner_def_id, proj_ty, values.found)
Expand Down
20 changes: 1 addition & 19 deletions compiler/rustc_infer/src/infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,25 +145,7 @@ impl<'tcx> InferCtxt<'tcx> {
return None;
}
}
DefiningAnchor::Bubble => {
if let ty::Alias(ty::Opaque, _) = b.kind() {
// In bubble mode we don't know which of the two opaque types is supposed to have the other
// as a hidden type (both, none or either one of them could be in its defining scope).
let predicate = ty::PredicateKind::AliasRelate(
a.into(),
b.into(),
ty::AliasRelationDirection::Equate,
);
let obligation = traits::Obligation::new(
self.tcx,
cause.clone(),
param_env,
predicate,
);
let obligations = vec![obligation];
return Some(Ok(InferOk { value: (), obligations }));
}
}
DefiningAnchor::Bubble => {}
DefiningAnchor::Error => return None,
};
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() {
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,11 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
if type_implements_negative_copy_modulo_regions(cx.tcx, ty, param_env) {
return;
}
if def.is_variant_list_non_exhaustive()
|| def.variants().iter().any(|variant| variant.is_field_list_non_exhaustive())
{
return;
}

// We shouldn't recommend implementing `Copy` on stateful things,
// such as iterators.
Expand Down
5 changes: 0 additions & 5 deletions compiler/rustc_middle/src/ty/generic_args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
use rustc_hir::def_id::DefId;
use rustc_macros::HashStable;
use rustc_serialize::{self, Decodable, Encodable};
use rustc_span::sym;
use rustc_type_ir::WithCachedTypeInfo;
use smallvec::SmallVec;

Expand Down Expand Up @@ -452,10 +451,6 @@ impl<'tcx> GenericArgs<'tcx> {
tcx.mk_args_from_iter(self.iter().take(generics.count()))
}

pub fn host_effect_param(&'tcx self) -> Option<ty::Const<'tcx>> {
self.consts().rfind(|x| matches!(x.kind(), ty::ConstKind::Param(p) if p.name == sym::host))
}

pub fn print_as_list(&self) -> String {
let v = self.iter().map(|arg| arg.to_string()).collect::<Vec<_>>();
format!("[{}]", v.join(", "))
Expand Down
23 changes: 2 additions & 21 deletions compiler/rustc_trait_selection/src/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use rustc_infer::infer::DefineOpaqueTypes;
use rustc_infer::traits::ProjectionCacheKey;
use rustc_infer::traits::{PolyTraitObligation, SelectionError, TraitEngine};
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::traits::DefiningAnchor;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::GenericArgsRef;
Expand Down Expand Up @@ -626,27 +625,9 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
}
}
ty::PredicateKind::Ambiguous => ProcessResult::Unchanged,
ty::PredicateKind::AliasRelate(..)
if matches!(self.selcx.infcx.defining_use_anchor, DefiningAnchor::Bubble) =>
{
ProcessResult::Unchanged
ty::PredicateKind::AliasRelate(..) => {
bug!("AliasRelate is only used for new solver")
}
ty::PredicateKind::AliasRelate(a, b, relate) => match relate {
ty::AliasRelationDirection::Equate => match self
.selcx
.infcx
.at(&obligation.cause, obligation.param_env)
.eq(DefineOpaqueTypes::Yes, a, b)
{
Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())),
Err(_) => ProcessResult::Error(FulfillmentErrorCode::CodeSelectionError(
SelectionError::Unimplemented,
)),
},
ty::AliasRelationDirection::Subtype => {
bug!("AliasRelate with subtyping is only used for new solver")
}
},
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq(
DefineOpaqueTypes::No,
Expand Down
23 changes: 2 additions & 21 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ use rustc_infer::traits::TraitObligation;
use rustc_middle::dep_graph::dep_kinds;
use rustc_middle::dep_graph::DepNodeIndex;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::traits::DefiningAnchor;
use rustc_middle::ty::_match::MatchAgainstFreshVars;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::fold::BottomUpFolder;
Expand Down Expand Up @@ -1005,27 +1004,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
}
ty::PredicateKind::AliasRelate(..)
if matches!(self.infcx.defining_use_anchor, DefiningAnchor::Bubble) =>
{
Ok(EvaluatedToAmbig)
ty::PredicateKind::AliasRelate(..) => {
bug!("AliasRelate is only used for new solver")
}
ty::PredicateKind::AliasRelate(a, b, relate) => match relate {
ty::AliasRelationDirection::Equate => match self
.infcx
.at(&obligation.cause, obligation.param_env)
.eq(DefineOpaqueTypes::Yes, a, b)
{
Ok(inf_ok) => self.evaluate_predicates_recursively(
previous_stack,
inf_ok.into_obligations(),
),
Err(_) => Ok(EvaluatedToErr),
},
ty::AliasRelationDirection::Subtype => {
bug!("AliasRelate subtyping is only used for new solver")
}
},
ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig),
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
match self.infcx.at(&obligation.cause, obligation.param_env).eq(
Expand Down
1 change: 0 additions & 1 deletion library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,6 @@
#![feature(doc_cfg)]
#![feature(doc_cfg_hide)]
#![feature(doc_notable_trait)]
#![feature(effects)]
#![feature(exhaustive_patterns)]
#![feature(extern_types)]
#![feature(fundamental)]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// run-rustfix
trait O {
type M;
}
trait U<A: O> {
const N: A::M;
}
impl<D> O for D {
type M = u8;
}
impl<C: O<M = u8>> U<C> for u16 {
const N: C::M = 4u8; //~ ERROR mismatched types
}
fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// run-rustfix
trait O {
type M;
}
trait U<A: O> {
const N: A::M;
}
impl<D> O for D {
type M = u8;
}
impl<C: O> U<C> for u16 {
const N: C::M = 4u8; //~ ERROR mismatched types
}
fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
error[E0308]: mismatched types
--> $DIR/suggest-contraining-assoc-type-because-of-assoc-const.rs:12:21
|
LL | const N: C::M = 4u8;
| ^^^ expected associated type, found `u8`
|
= note: expected associated type `<C as O>::M`
found type `u8`
help: consider constraining the associated type `<C as O>::M` to `u8`
|
LL | impl<C: O<M = u8>> U<C> for u16 {
| ++++++++

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
11 changes: 11 additions & 0 deletions tests/ui/consts/effect_param.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//! Ensure we don't allow accessing const effect parameters from stable Rust.
fn main() {
i8::checked_sub::<true>(42, 43);
//~^ ERROR: method takes 0 generic arguments but 1 generic argument was supplied
}

const FOO: () = {
i8::checked_sub::<false>(42, 43);
//~^ ERROR: method takes 0 generic arguments but 1 generic argument was supplied
};
Loading

0 comments on commit e1de04a

Please sign in to comment.