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

Add new rpitit compare mode #108710

Closed
Closed
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
9 changes: 8 additions & 1 deletion compiler/rustc_hir_analysis/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3049,10 +3049,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
&hir::TyKind::OpaqueDef(item_id, lifetimes, in_trait) => {
let opaque_ty = tcx.hir().item(item_id);
let def_id = item_id.owner_id.to_def_id();

match opaque_ty.kind {
hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => {
let local_def_id = item_id.owner_id.def_id;
let def_id = if in_trait
&& tcx.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty
{
tcx.associated_item_for_impl_trait_in_trait(local_def_id).to_def_id()
} else {
local_def_id.to_def_id()
};
self.impl_trait_ty_to_ty(def_id, lifetimes, origin, in_trait)
}
ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
Expand Down
27 changes: 19 additions & 8 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -831,7 +831,14 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {

fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
if let ty::Alias(ty::Projection, proj) = ty.kind()
&& self.interner().def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
&& (self.interner().def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
|| self
.interner()
.sess
.opts
.unstable_opts
.lower_impl_trait_in_trait_to_assoc_ty
&& self.interner().def_kind(proj.def_id) == DefKind::AssocTy)
{
if let Some((ty, _)) = self.types.get(&proj.def_id) {
return *ty;
Expand Down Expand Up @@ -1996,13 +2003,17 @@ pub(super) fn check_type_bounds<'tcx>(
let infcx = tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx);

let impl_ty_span = match tcx.hir().get_by_def_id(impl_ty_def_id) {
hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Type(_, Some(ty)),
..
}) => ty.span,
hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Type(ty), .. }) => ty.span,
_ => bug!(),
let impl_ty_span = if tcx.opt_rpitit_info(impl_ty_def_id).is_some() {
tcx.def_span(impl_ty_def_id)
} else {
match tcx.hir().get_by_def_id(impl_ty_def_id) {
hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Type(_, Some(ty)),
..
}) => ty.span,
hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Type(ty), .. }) => ty.span,
_ => bug!(),
}
};
let assumed_wf_types = ocx.assumed_wf_types(param_env, impl_ty_span, impl_ty_def_id);

Expand Down
32 changes: 21 additions & 11 deletions compiler/rustc_hir_analysis/src/collect/item_bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::astconv::AstConv;
use rustc_hir as hir;
use rustc_infer::traits::util;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::{self, DefIdTree, TyCtxt};
use rustc_middle::ty::{self, DefIdTree, ImplTraitInTraitData, Ty, TyCtxt};
use rustc_span::def_id::DefId;
use rustc_span::Span;

Expand Down Expand Up @@ -58,17 +58,10 @@ fn opaque_type_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
opaque_def_id: DefId,
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
item_ty: Ty<'tcx>,
span: Span,
in_trait: bool,
) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
ty::print::with_no_queries!({
let substs = InternalSubsts::identity_for_item(tcx, opaque_def_id);
let item_ty = if in_trait {
tcx.mk_projection(opaque_def_id, substs)
} else {
tcx.mk_opaque(opaque_def_id, substs)
};

let icx = ItemCtxt::new(tcx, opaque_def_id);
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds);
// Opaque types are implicitly sized unless a `?Sized` bound is found
Expand All @@ -83,7 +76,16 @@ pub(super) fn explicit_item_bounds(
tcx: TyCtxt<'_>,
def_id: DefId,
) -> &'_ [(ty::Predicate<'_>, Span)] {
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let rpitit_info = if let Some(ImplTraitInTraitData::Trait { opaque_def_id, .. }) =
tcx.opt_rpitit_info(def_id)
{
Some(opaque_def_id)
} else {
None
};

let bounds_def_id = rpitit_info.unwrap_or(def_id);
let hir_id = tcx.hir().local_def_id_to_hir_id(bounds_def_id.expect_local());
match tcx.hir().get(hir_id) {
hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Type(bounds, _),
Expand All @@ -94,7 +96,15 @@ pub(super) fn explicit_item_bounds(
kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait, .. }),
span,
..
}) => opaque_type_bounds(tcx, def_id, bounds, *span, *in_trait),
}) => {
let substs = InternalSubsts::identity_for_item(tcx, def_id);
let item_ty = if *in_trait && rpitit_info.is_none() {
tcx.mk_projection(def_id, substs)
} else {
tcx.mk_opaque(def_id, substs)
};
opaque_type_bounds(tcx, bounds_def_id, bounds, item_ty, *span)
}
_ => bug!("item_bounds called on {:?}", def_id),
}
}
Expand Down
18 changes: 17 additions & 1 deletion compiler/rustc_hir_analysis/src/collect/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{
self, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
self, DefIdTree, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, TypeFolder,
TypeSuperFoldable, TypeVisitableExt,
};
use rustc_span::symbol::Ident;
use rustc_span::{Span, DUMMY_SP};
Expand Down Expand Up @@ -244,6 +245,21 @@ fn get_path_containing_arg_in_pat<'hir>(
}

pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>> {
if let Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) = tcx.opt_rpitit_info(def_id) {
match tcx.collect_return_position_impl_trait_in_trait_tys(fn_def_id) {
Ok(map) => {
let assoc_item = tcx.associated_item(def_id);
return ty::EarlyBinder(map[&assoc_item.trait_item_def_id.unwrap()]);
}
Err(_) => {
return ty::EarlyBinder(tcx.ty_error_with_message(
DUMMY_SP,
"Could not collect return position impl trait in trait tys",
));
}
}
}

let def_id = def_id.expect_local();
use rustc_hir::*;

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1324,6 +1324,7 @@ rustc_queries! {
/// might want to use `reveal_all()` method to change modes.
query param_env(def_id: DefId) -> ty::ParamEnv<'tcx> {
desc { |tcx| "computing normalized predicates of `{}`", tcx.def_path_str(def_id) }
feedable
}

/// Like `param_env`, but returns the `ParamEnv` in `Reveal::All` mode.
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_passes/src/dead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,11 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
continue;
}

if self.tcx.opt_rpitit_info(id).is_some() {
self.live_symbols.insert(id);
continue;
}

// in the case of tuple struct constructors we want to check the item, not the generated
// tuple struct constructor function
let id = self.struct_constructors.get(&id).copied().unwrap_or(id);
Expand Down
54 changes: 45 additions & 9 deletions compiler/rustc_ty_utils/src/assoc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,9 +302,6 @@ fn associated_item_for_impl_trait_in_trait(
// There are no inferred outlives for the synthesized associated type.
trait_assoc_ty.inferred_outlives_of(&[]);

// FIXME implement this.
trait_assoc_ty.explicit_item_bounds(&[]);

local_def_id
}

Expand All @@ -316,11 +313,12 @@ fn impl_associated_item_for_impl_trait_in_trait(
trait_assoc_def_id: LocalDefId,
impl_fn_def_id: LocalDefId,
) -> LocalDefId {
let impl_def_id = tcx.local_parent(impl_fn_def_id);
let impl_def_id = tcx.parent(impl_fn_def_id.to_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 impl_assoc_ty = tcx.at(span).create_def(impl_def_id, DefPathData::ImplTraitAssocTy);
let impl_assoc_ty =
tcx.at(span).create_def(impl_def_id.expect_local(), DefPathData::ImplTraitAssocTy);

let local_def_id = impl_assoc_ty.def_id();
let def_id = local_def_id.to_def_id();
Expand All @@ -345,13 +343,51 @@ fn impl_associated_item_for_impl_trait_in_trait(
fn_has_self_parameter: false,
});

impl_assoc_ty.param_env(tcx.param_env(impl_fn_def_id));

// Copy impl_defaultness of the containing function.
impl_assoc_ty.impl_defaultness(tcx.impl_defaultness(impl_fn_def_id));

// Copy generics_of the trait's associated item.
// FIXME: This is not correct, in particular the parent is going to be wrong. So we would need
// to copy from trait_assoc_def_id and adjust things.
impl_assoc_ty.generics_of(tcx.generics_of(trait_assoc_def_id).clone());
// Copy generics_of the trait's associated item but the impl as the parent.
impl_assoc_ty.generics_of({
let trait_assoc_generics = tcx.generics_of(trait_assoc_def_id);
let trait_assoc_parent_count = trait_assoc_generics.parent_count;
let mut params = trait_assoc_generics.params.clone();

let parent_generics = tcx.generics_of(impl_def_id);
let parent_count = parent_generics.parent_count + parent_generics.params.len();

let mut impl_fn_params = tcx.generics_of(impl_fn_def_id).params.clone();

for param in &mut params {
param.index = param.index + parent_count as u32 + impl_fn_params.len() as u32
- trait_assoc_parent_count as u32;
}

impl_fn_params.extend(params);
params = impl_fn_params;

let param_def_id_to_index =
params.iter().map(|param| (param.def_id, param.index)).collect();

ty::Generics {
parent: Some(impl_def_id),
parent_count,
params,
param_def_id_to_index,
has_self: false,
has_late_bound_regions: trait_assoc_generics.has_late_bound_regions,
}
});

// There are no predicates for the synthesized associated type.
impl_assoc_ty.explicit_predicates_of(ty::GenericPredicates {
parent: Some(impl_def_id),
predicates: &[],
});

// There are no inferred outlives for the synthesized associated type.
impl_assoc_ty.inferred_outlives_of(&[]);

local_def_id
}
11 changes: 9 additions & 2 deletions compiler/rustc_ty_utils/src/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_index::bit_set::BitSet;
use rustc_middle::ty::{
self, Binder, EarlyBinder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt,
TypeSuperVisitable, TypeVisitable, TypeVisitor,
self, Binder, EarlyBinder, ImplTraitInTraitData, Predicate, PredicateKind, ToPredicate, Ty,
TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
};
use rustc_session::config::TraitSolver;
use rustc_span::def_id::{DefId, CRATE_DEF_ID};
Expand Down Expand Up @@ -117,6 +117,13 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] {

/// See `ParamEnv` struct definition for details.
fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
let def_id =
if let Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) = tcx.opt_rpitit_info(def_id) {
fn_def_id
} else {
def_id
};

// Compute the bounds on Self and the type parameters.
let ty::InstantiatedPredicates { mut predicates, .. } =
tcx.predicates_of(def_id).instantiate_identity(tcx);
Expand Down
3 changes: 3 additions & 0 deletions src/tools/compiletest/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ pub enum FailMode {
pub enum CompareMode {
Polonius,
Chalk,
LowerImplTraitInTraitToAssocTy,
NextSolver,
SplitDwarf,
SplitDwarfSingle,
Expand All @@ -133,6 +134,7 @@ impl CompareMode {
match *self {
CompareMode::Polonius => "polonius",
CompareMode::Chalk => "chalk",
CompareMode::LowerImplTraitInTraitToAssocTy => "lower-impl-trait-in-trait-to-assoc-ty",
CompareMode::NextSolver => "next-solver",
CompareMode::SplitDwarf => "split-dwarf",
CompareMode::SplitDwarfSingle => "split-dwarf-single",
Expand All @@ -143,6 +145,7 @@ impl CompareMode {
match s.as_str() {
"polonius" => CompareMode::Polonius,
"chalk" => CompareMode::Chalk,
"lower-impl-trait-in-trait-to-assoc-ty" => CompareMode::LowerImplTraitInTraitToAssocTy,
"next-solver" => CompareMode::NextSolver,
"split-dwarf" => CompareMode::SplitDwarf,
"split-dwarf-single" => CompareMode::SplitDwarfSingle,
Expand Down
1 change: 1 addition & 0 deletions src/tools/compiletest/src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,7 @@ impl Config {
match self.compare_mode {
Some(CompareMode::Polonius) => name == "compare-mode-polonius",
Some(CompareMode::Chalk) => name == "compare-mode-chalk",
Some(CompareMode::LowerImplTraitInTraitToAssocTy) => name == "compare-mode-lower-impl-trait-in-trait-to-assoc-ty",
Some(CompareMode::NextSolver) => name == "compare-mode-next-solver",
Some(CompareMode::SplitDwarf) => name == "compare-mode-split-dwarf",
Some(CompareMode::SplitDwarfSingle) => name == "compare-mode-split-dwarf-single",
Expand Down
3 changes: 3 additions & 0 deletions src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2030,6 +2030,9 @@ impl<'test> TestCx<'test> {
Some(CompareMode::Chalk) => {
rustc.args(&["-Ztrait-solver=chalk"]);
}
Some(CompareMode::LowerImplTraitInTraitToAssocTy) => {
rustc.args(&["-Zlower-impl-trait-in-trait-to-assoc-ty"]);
}
Some(CompareMode::NextSolver) => {
rustc.args(&["-Ztrait-solver=next"]);
}
Expand Down
1 change: 1 addition & 0 deletions tests/ui/async-await/async-trait-fn.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// ignore-compare-mode-lower-impl-trait-in-trait-to-assoc-ty
// edition:2018
trait T {
async fn foo() {} //~ ERROR functions in traits cannot be declared `async`
Expand Down
6 changes: 3 additions & 3 deletions tests/ui/async-await/async-trait-fn.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0706]: functions in traits cannot be declared `async`
--> $DIR/async-trait-fn.rs:3:5
--> $DIR/async-trait-fn.rs:4:5
|
LL | async fn foo() {}
| -----^^^^^^^^^
Expand All @@ -12,7 +12,7 @@ LL | async fn foo() {}
= help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable

error[E0706]: functions in traits cannot be declared `async`
--> $DIR/async-trait-fn.rs:4:5
--> $DIR/async-trait-fn.rs:5:5
|
LL | async fn bar(&self) {}
| -----^^^^^^^^^^^^^^
Expand All @@ -25,7 +25,7 @@ LL | async fn bar(&self) {}
= help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable

error[E0706]: functions in traits cannot be declared `async`
--> $DIR/async-trait-fn.rs:5:5
--> $DIR/async-trait-fn.rs:6:5
|
LL | async fn baz() {
| -----^^^^^^^^^
Expand Down
1 change: 1 addition & 0 deletions tests/ui/async-await/edition-deny-async-fns-2015.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// edition:2015
// ignore-compare-mode-lower-impl-trait-in-trait-to-assoc-ty

async fn foo() {} //~ ERROR `async fn` is not permitted in Rust 2015

Expand Down
Loading