Skip to content

Commit

Permalink
Auto merge of #106129 - compiler-errors:compare_method-tweaks, r=BoxyUwU
Browse files Browse the repository at this point in the history
Some `compare_method` tweaks

1. Make some of the comparison functions' names more regular
2. Reduce pub scope of some of the things in `compare_method`
~3. Remove some unnecessary opaque type handling code -- `InferCtxt` already is in a mode that doesn't define opaque types~
  * moved to a different PR
4. Bubble up `ErrorGuaranteed` for region constraint errors in `compare_method` - Improves a redundant error message in one unit test.
5. Move the `compare_method` module to have a more general name, since it's more like `compare_impl_item` :)
6. Rename `collect_trait_impl_trait_tys`
  • Loading branch information
bors committed Dec 28, 2022
2 parents 6a20f7d + 96d8011 commit 83a28ef
Show file tree
Hide file tree
Showing 17 changed files with 89 additions and 72 deletions.
10 changes: 5 additions & 5 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::check::intrinsicck::InlineAsmCtxt;
use crate::errors::LinkageType;

use super::compare_method::check_type_bounds;
use super::compare_method::{compare_impl_method, compare_ty_impl};
use super::compare_impl_item::check_type_bounds;
use super::compare_impl_item::{compare_impl_method, compare_impl_ty};
use super::*;
use rustc_attr as attr;
use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan};
Expand Down Expand Up @@ -468,7 +468,7 @@ fn check_opaque_meets_bounds<'tcx>(
// Can have different predicates to their defining use
hir::OpaqueTyOrigin::TyAlias => {
let outlives_environment = OutlivesEnvironment::new(param_env);
infcx.check_region_obligations_and_report_errors(
let _ = infcx.check_region_obligations_and_report_errors(
defining_use_anchor,
&outlives_environment,
);
Expand Down Expand Up @@ -774,7 +774,7 @@ fn check_impl_items_against_trait<'tcx>(
let impl_item_full = tcx.hir().impl_item(impl_item.id);
match impl_item_full.kind {
hir::ImplItemKind::Const(..) => {
let _ = tcx.compare_assoc_const_impl_item_with_trait_item((
let _ = tcx.compare_impl_const((
impl_item.id.owner_id.def_id,
ty_impl_item.trait_item_def_id.unwrap(),
));
Expand All @@ -791,7 +791,7 @@ fn check_impl_items_against_trait<'tcx>(
}
hir::ImplItemKind::Type(impl_ty) => {
let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
compare_ty_impl(
compare_impl_ty(
tcx,
&ty_impl_item,
impl_ty.span,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use std::iter;
/// - `impl_m_span`: span to use for reporting errors
/// - `trait_m`: the method in the trait
/// - `impl_trait_ref`: the TraitRef corresponding to the trait implementation
pub(crate) fn compare_impl_method<'tcx>(
pub(super) fn compare_impl_method<'tcx>(
tcx: TyCtxt<'tcx>,
impl_m: &ty::AssocItem,
trait_m: &ty::AssocItem,
Expand Down Expand Up @@ -71,7 +71,7 @@ pub(crate) fn compare_impl_method<'tcx>(
return;
}

if let Err(_) = compare_predicate_entailment(
if let Err(_) = compare_method_predicate_entailment(
tcx,
impl_m,
impl_m_span,
Expand Down Expand Up @@ -150,7 +150,7 @@ pub(crate) fn compare_impl_method<'tcx>(
/// Finally we register each of these predicates as an obligation and check that
/// they hold.
#[instrument(level = "debug", skip(tcx, impl_m_span, impl_trait_ref))]
fn compare_predicate_entailment<'tcx>(
fn compare_method_predicate_entailment<'tcx>(
tcx: TyCtxt<'tcx>,
impl_m: &ty::AssocItem,
impl_m_span: Span,
Expand Down Expand Up @@ -337,7 +337,7 @@ fn compare_predicate_entailment<'tcx>(
if !errors.is_empty() {
match check_implied_wf {
CheckImpliedWfMode::Check => {
return compare_predicate_entailment(
return compare_method_predicate_entailment(
tcx,
impl_m,
impl_m_span,
Expand Down Expand Up @@ -374,7 +374,7 @@ fn compare_predicate_entailment<'tcx>(
// becomes a hard error (i.e. ideally we'd just call `resolve_regions_and_report_errors`
match check_implied_wf {
CheckImpliedWfMode::Check => {
return compare_predicate_entailment(
return compare_method_predicate_entailment(
tcx,
impl_m,
impl_m_span,
Expand Down Expand Up @@ -407,7 +407,7 @@ enum CheckImpliedWfMode {
/// re-check with `Skip`, and emit a lint if it succeeds.
Check,
/// Skips checking implied well-formedness of the impl method, but will emit
/// a lint if the `compare_predicate_entailment` succeeded. This means that
/// a lint if the `compare_method_predicate_entailment` succeeded. This means that
/// the reason that we had failed earlier during `Check` was due to the impl
/// having stronger requirements than the trait.
Skip,
Expand Down Expand Up @@ -441,8 +441,41 @@ fn compare_asyncness<'tcx>(
Ok(())
}

/// Given a method def-id in an impl, compare the method signature of the impl
/// against the trait that it's implementing. In doing so, infer the hidden types
/// that this method's signature provides to satisfy each return-position `impl Trait`
/// in the trait signature.
///
/// The method is also responsible for making sure that the hidden types for each
/// RPITIT actually satisfy the bounds of the `impl Trait`, i.e. that if we infer
/// `impl Trait = Foo`, that `Foo: Trait` holds.
///
/// For example, given the sample code:
///
/// ```
/// #![feature(return_position_impl_trait_in_trait)]
///
/// use std::ops::Deref;
///
/// trait Foo {
/// fn bar() -> impl Deref<Target = impl Sized>;
/// // ^- RPITIT #1 ^- RPITIT #2
/// }
///
/// impl Foo for () {
/// fn bar() -> Box<String> { Box::new(String::new()) }
/// }
/// ```
///
/// The hidden types for the RPITITs in `bar` would be inferred to:
/// * `impl Deref` (RPITIT #1) = `Box<String>`
/// * `impl Sized` (RPITIT #2) = `String`
///
/// The relationship between these two types is straightforward in this case, but
/// may be more tenuously connected via other `impl`s and normalization rules for
/// cases of more complicated nested RPITITs.
#[instrument(skip(tcx), level = "debug", ret)]
pub fn collect_trait_impl_trait_tys<'tcx>(
pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: DefId,
) -> Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed> {
Expand Down Expand Up @@ -550,13 +583,13 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
// Unify the whole function signature. We need to do this to fully infer
// the lifetimes of the return type, but do this after unifying just the
// return types, since we want to avoid duplicating errors from
// `compare_predicate_entailment`.
// `compare_method_predicate_entailment`.
match ocx.eq(&cause, param_env, trait_fty, impl_fty) {
Ok(()) => {}
Err(terr) => {
// This function gets called during `compare_predicate_entailment` when normalizing a
// This function gets called during `compare_method_predicate_entailment` when normalizing a
// signature that contains RPITIT. When the method signatures don't match, we have to
// emit an error now because `compare_predicate_entailment` will not report the error
// emit an error now because `compare_method_predicate_entailment` will not report the error
// when normalization fails.
let emitted = report_trait_method_mismatch(
infcx,
Expand Down Expand Up @@ -589,7 +622,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
infcx.check_region_obligations_and_report_errors(
impl_m.def_id.expect_local(),
&outlives_environment,
);
)?;

let mut collected_tys = FxHashMap::default();
for (def_id, (ty, substs)) in collector.types {
Expand Down Expand Up @@ -1516,8 +1549,8 @@ fn compare_generic_param_kinds<'tcx>(
Ok(())
}

/// Use `tcx.compare_assoc_const_impl_item_with_trait_item` instead
pub(crate) fn raw_compare_const_impl(
/// Use `tcx.compare_impl_const` instead
pub(super) fn compare_impl_const_raw(
tcx: TyCtxt<'_>,
(impl_const_item_def, trait_const_item_def): (LocalDefId, DefId),
) -> Result<(), ErrorGuaranteed> {
Expand Down Expand Up @@ -1617,13 +1650,13 @@ pub(crate) fn raw_compare_const_impl(
return Err(infcx.err_ctxt().report_fulfillment_errors(&errors, None));
}

// FIXME return `ErrorReported` if region obligations error?
let outlives_environment = OutlivesEnvironment::new(param_env);
infcx.check_region_obligations_and_report_errors(impl_const_item_def, &outlives_environment);
infcx.check_region_obligations_and_report_errors(impl_const_item_def, &outlives_environment)?;

Ok(())
}

pub(crate) fn compare_ty_impl<'tcx>(
pub(super) fn compare_impl_ty<'tcx>(
tcx: TyCtxt<'tcx>,
impl_ty: &ty::AssocItem,
impl_ty_span: Span,
Expand All @@ -1645,7 +1678,7 @@ pub(crate) fn compare_ty_impl<'tcx>(
})();
}

/// The equivalent of [compare_predicate_entailment], but for associated types
/// The equivalent of [compare_method_predicate_entailment], but for associated types
/// instead of associated functions.
fn compare_type_predicate_entailment<'tcx>(
tcx: TyCtxt<'tcx>,
Expand Down Expand Up @@ -1730,7 +1763,7 @@ fn compare_type_predicate_entailment<'tcx>(
infcx.check_region_obligations_and_report_errors(
impl_ty.def_id.expect_local(),
&outlives_environment,
);
)?;

Ok(())
}
Expand All @@ -1749,7 +1782,7 @@ fn compare_type_predicate_entailment<'tcx>(
/// from the impl could be overridden). We also can't normalize generic
/// associated types (yet) because they contain bound parameters.
#[instrument(level = "debug", skip(tcx))]
pub fn check_type_bounds<'tcx>(
pub(super) fn check_type_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
trait_ty: &ty::AssocItem,
impl_ty: &ty::AssocItem,
Expand Down Expand Up @@ -1944,7 +1977,7 @@ pub fn check_type_bounds<'tcx>(
infcx.check_region_obligations_and_report_errors(
impl_ty.def_id.expect_local(),
&outlives_environment,
);
)?;

let constraints = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
for (key, value) in constraints {
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_hir_analysis/src/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ a type parameter).
*/

mod check;
mod compare_method;
mod compare_impl_item;
pub mod dropck;
pub mod intrinsic;
pub mod intrinsicck;
Expand Down Expand Up @@ -94,7 +94,7 @@ use std::num::NonZeroU32;
use crate::require_c_abi_if_c_variadic;
use crate::util::common::indenter;

use self::compare_method::collect_trait_impl_trait_tys;
use self::compare_impl_item::collect_return_position_impl_trait_in_trait_tys;
use self::region::region_scope_tree;

pub fn provide(providers: &mut Providers) {
Expand All @@ -103,8 +103,8 @@ pub fn provide(providers: &mut Providers) {
adt_destructor,
check_mod_item_types,
region_scope_tree,
collect_trait_impl_trait_tys,
compare_assoc_const_impl_item_with_trait_item: compare_method::raw_compare_const_impl,
collect_return_position_impl_trait_in_trait_tys,
compare_impl_const: compare_impl_item::compare_impl_const_raw,
..*providers
};
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
let outlives_environment =
OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds);

infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment);
let _ = infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment);
}

fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/coherence/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef

// Finally, resolve all regions.
let outlives_env = OutlivesEnvironment::new(param_env);
infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env);
let _ = infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env);
}
}
_ => {
Expand Down Expand Up @@ -565,7 +565,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn

// Finally, resolve all regions.
let outlives_env = OutlivesEnvironment::new(param_env);
infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env);
let _ = infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env);

CoerceUnsizedInfo { custom_kind: kind }
}
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ fn get_impl_substs(

let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_hir_id, assumed_wf_types);
let outlives_env = OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds);
infcx.check_region_obligations_and_report_errors(impl1_def_id, &outlives_env);
let _ = infcx.check_region_obligations_and_report_errors(impl1_def_id, &outlives_env);
let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
let span = tcx.def_span(impl1_def_id);
tcx.sess.emit_err(SubstsOnOverriddenImpl { span });
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1836,7 +1836,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {

// In some (most?) cases cause.body_id points to actual body, but in some cases
// it's an actual definition. According to the comments (e.g. in
// rustc_hir_analysis/check/compare_method.rs:compare_predicate_entailment) the latter
// rustc_hir_analysis/check/compare_impl_item.rs:compare_predicate_entailment) the latter
// is relied upon by some other code. This might (or might not) need cleanup.
let body_owner_def_id =
self.tcx.hir().opt_local_def_id(cause.body_id).unwrap_or_else(|| {
Expand Down
13 changes: 9 additions & 4 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1693,7 +1693,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
&self,
generic_param_scope: LocalDefId,
outlives_env: &OutlivesEnvironment<'tcx>,
) -> Option<ErrorGuaranteed> {
) -> Result<(), ErrorGuaranteed> {
let errors = self.resolve_regions(outlives_env);

if let None = self.tainted_by_errors() {
Expand All @@ -1705,9 +1705,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
self.report_region_errors(generic_param_scope, &errors);
}

(!errors.is_empty()).then(|| {
self.tcx.sess.delay_span_bug(rustc_span::DUMMY_SP, "error should have been emitted")
})
if errors.is_empty() {
Ok(())
} else {
Err(self
.tcx
.sess
.delay_span_bug(rustc_span::DUMMY_SP, "error should have been emitted"))
}
}

// [Note-Type-error-reporting]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/outlives/obligations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ impl<'tcx> InferCtxt<'tcx> {
&self,
generic_param_scope: LocalDefId,
outlives_env: &OutlivesEnvironment<'tcx>,
) -> Option<ErrorGuaranteed> {
) -> Result<(), ErrorGuaranteed> {
self.process_registered_region_obligations(
outlives_env.region_bound_pairs(),
outlives_env.param_env,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ provide! { tcx, def_id, other, cdata,
generator_kind => { table }
trait_def => { table }
deduced_param_attrs => { table }
collect_trait_impl_trait_tys => {
collect_return_position_impl_trait_in_trait_tys => {
Ok(cdata
.root
.tables
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1197,7 +1197,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
record!(self.tables.params_in_repr[def_id] <- params_in_repr);
}
if should_encode_trait_impl_trait_tys(tcx, def_id)
&& let Ok(table) = self.tcx.collect_trait_impl_trait_tys(def_id)
&& let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
{
record!(self.tables.trait_impl_trait_tys[def_id] <- table);
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ rustc_queries! {
separate_provide_extern
}

query collect_trait_impl_trait_tys(key: DefId)
query collect_return_position_impl_trait_in_trait_tys(key: DefId)
-> Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed>
{
desc { "comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process" }
Expand Down Expand Up @@ -2117,7 +2117,7 @@ rustc_queries! {
desc { "checking to see if `{}` permits being left zeroed", key.ty }
}

query compare_assoc_const_impl_item_with_trait_item(
query compare_impl_const(
key: (LocalDefId, DefId)
) -> Result<(), ErrorGuaranteed> {
desc { |tcx| "checking assoc const `{}` has the same type as trait item", tcx.def_path_str(key.0.to_def_id()) }
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -641,11 +641,11 @@ impl<'tcx> TyCtxt<'tcx> {
ty::EarlyBinder(self.type_of(def_id))
}

pub fn bound_trait_impl_trait_tys(
pub fn bound_return_position_impl_trait_in_trait_tys(
self,
def_id: DefId,
) -> ty::EarlyBinder<Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed>> {
ty::EarlyBinder(self.collect_trait_impl_trait_tys(def_id))
ty::EarlyBinder(self.collect_return_position_impl_trait_in_trait_tys(def_id))
}

pub fn bound_fn_sig(self, def_id: DefId) -> ty::EarlyBinder<ty::PolyFnSig<'tcx>> {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2284,7 +2284,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
obligation.param_env,
cause.clone(),
obligation.recursion_depth + 1,
tcx.bound_trait_impl_trait_tys(impl_fn_def_id)
tcx.bound_return_position_impl_trait_in_trait_tys(impl_fn_def_id)
.map_bound(|tys| {
tys.map_or_else(|_| tcx.ty_error(), |tys| tys[&obligation.predicate.def_id])
})
Expand Down
Loading

0 comments on commit 83a28ef

Please sign in to comment.