Skip to content
Open
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
25 changes: 20 additions & 5 deletions compiler/rustc_public/src/compiler_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ use crate::mir::mono::{Instance, InstanceDef, StaticDef};
use crate::mir::{BinOp, Body, Place, UnOp};
use crate::target::{MachineInfo, MachineSize};
use crate::ty::{
AdtDef, AdtKind, Allocation, Asyncness, ClosureDef, ClosureKind, Constness, CoroutineDef,
Discr, FieldDef, FnDef, ForeignDef, ForeignItemKind, ForeignModule, ForeignModuleDef,
GenericArgs, GenericPredicates, Generics, ImplDef, ImplTrait, IntrinsicDef, LineInfo, MirConst,
PolyFnSig, RigidTy, Span, TraitDecl, TraitDef, TraitRef, Ty, TyConst, TyConstId, TyKind,
UintTy, VariantDef, VariantIdx, VtblEntry,
AdtDef, AdtKind, Allocation, AssocItem, Asyncness, ClosureDef, ClosureKind, Constness,
CoroutineDef, Discr, FieldDef, FnDef, ForeignDef, ForeignItemKind, ForeignModule,
ForeignModuleDef, GenericArgs, GenericPredicates, Generics, ImplDef, ImplTrait, IntrinsicDef,
LineInfo, MirConst, PolyFnSig, RigidTy, Span, TraitDecl, TraitDef, TraitRef, Ty, TyConst,
TyConstId, TyKind, UintTy, VariantDef, VariantIdx, VtblEntry,
};
use crate::unstable::{RustcInternal, Stable, new_item_kind};
use crate::{
Expand Down Expand Up @@ -210,6 +210,13 @@ impl<'tcx> CompilerInterface<'tcx> {
})
}

pub(crate) fn inherent_impls(&self, adt: AdtDef) -> Vec<ImplDef> {
self.with_cx(|tables, cx| {
let def_id = tables[adt.0];
cx.tcx.inherent_impls(def_id).iter().map(|&did| tables.impl_def(did)).collect()
})
}

pub(crate) fn predicates_of(&self, def_id: DefId) -> GenericPredicates {
self.with_cx(|tables, cx| {
let did = tables[def_id];
Expand Down Expand Up @@ -821,6 +828,14 @@ impl<'tcx> CompilerInterface<'tcx> {
})
}

/// Get the associated item of a definition if it is one.
pub(crate) fn associated_item(&self, def_id: DefId) -> Option<AssocItem> {
self.with_cx(|tables, cx| {
let did = tables[def_id];
cx.associated_item(did).map(|assoc| assoc.stable(tables, cx))
})
}

/// Get all associated items of a definition.
pub(crate) fn associated_items(&self, def_id: DefId) -> AssocItems {
self.with_cx(|tables, cx| {
Expand Down
27 changes: 26 additions & 1 deletion compiler/rustc_public/src/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,16 @@ impl FnDef {
let kind = self.ty().kind();
kind.fn_sig().unwrap()
}

/// Get the generics of this function definition.
pub fn generics_of(&self) -> Generics {
with(|cx| cx.generics_of(self.0))
}

/// Get the associated item information if this function is one.
pub fn associated_item(&self) -> Option<AssocItem> {
with(|cx| cx.associated_item(self.0))
}
}

crate_def_with_ty! {
Expand Down Expand Up @@ -863,6 +873,16 @@ impl AdtDef {
pub fn discriminant_for_variant(&self, idx: VariantIdx) -> Discr {
with(|cx| cx.adt_discr_for_variant(*self, idx))
}

/// Get the generics of this ADT definition.
pub fn generics_of(&self) -> Generics {
with(|cx| cx.generics_of(self.0))
}

/// Retrieve the inherent implementations for this ADT.
pub fn inherent_impls(&self) -> Vec<ImplDef> {
with(|cx| cx.inherent_impls(*self))
}
}

pub struct Discr {
Expand Down Expand Up @@ -970,7 +990,7 @@ crate_def_with_ty! {
pub ConstDef;
}

crate_def! {
crate_def_with_ty! {
/// A trait impl definition.
#[derive(Serialize)]
pub ImplDef;
Expand All @@ -985,6 +1005,11 @@ impl ImplDef {
pub fn associated_items(&self) -> AssocItems {
with(|cx| cx.associated_items(self.def_id()))
}

/// Get the generics of this implementation.
pub fn generics_of(&self) -> Generics {
with(|cx| cx.generics_of(self.0))
}
}

crate_def! {
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_public_bridge/src/context/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,10 @@ impl<'tcx, B: Bridge> CompilerCtxt<'tcx, B> {
assoc_items
}

pub fn associated_item(&self, def_id: DefId) -> Option<AssocItem> {
self.tcx.opt_associated_item(def_id)
}

/// Get all vtable entries of a trait.
pub fn vtable_entries(&self, trait_ref: TraitRef<'tcx>) -> Vec<VtblEntry<'tcx>> {
self.tcx.vtable_entries(trait_ref).to_vec()
Expand Down
74 changes: 74 additions & 0 deletions tests/ui-fulldeps/rustc_public/check_alias.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
//@ run-pass
//! Test that alias type conversion (projection/opaque types) works and returns TyKind::Alias.

//@ ignore-stage1
//@ ignore-cross-compile
//@ ignore-remote
//@ edition: 2021

#![feature(rustc_private)]

extern crate rustc_middle;

extern crate rustc_driver;
extern crate rustc_interface;
#[macro_use]
extern crate rustc_public;

use rustc_public::CrateDef;
use rustc_public::ty::{TyKind, AliasKind};
use std::ops::ControlFlow;

const CRATE_NAME: &str = "crate_alias";

fn test_alias() -> ControlFlow<()> {
let local_crate = rustc_public::local_crate();
let fn_defs = local_crate.fn_defs();
let alias_fn = fn_defs
.iter()
.find(|f| f.trimmed_name().as_str() == "alias_fn")
.expect("Failed to find alias_fn");
let fn_sig = alias_fn.fn_sig().skip_binder();
let inputs = fn_sig.inputs();
assert_eq!(inputs.len(), 1);
let input_ty = &inputs[0];
match input_ty.kind() {
TyKind::Alias(alias_kind, alias_ty) => {
assert_eq!(alias_kind, AliasKind::Projection);
assert_eq!(alias_ty.def_id.trimmed_name().as_str(), "MyTrait::Assoc");
}
_ => panic!("Expected TyKind::Alias for input type, found {:?}", input_ty),
}

ControlFlow::Continue(())
}

fn main() {
let path = "alias.rs";
generate_input(&path).unwrap();
let args = &[
"rustc".to_string(),
"--crate-type=lib".to_string(),
"--crate-name".to_string(),
CRATE_NAME.to_string(),
path.to_string(),
];
run!(args, test_alias).unwrap();
}

fn generate_input(path: &str) -> std::io::Result<()> {
std::fs::write(
path,
r#"
pub trait MyTrait {
type Assoc;
}

impl MyTrait for i32 {
type Assoc = bool;
}

pub fn alias_fn<T: MyTrait>(val: T::Assoc) {}
"#
)
}
76 changes: 76 additions & 0 deletions tests/ui-fulldeps/rustc_public/check_generics.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//@ run-pass
//! Test that users are able to retrieve generic parameters from various definitions.

//@ ignore-stage1
//@ ignore-cross-compile
//@ ignore-remote
//@ edition: 2021

#![feature(rustc_private)]

extern crate rustc_middle;

extern crate rustc_driver;
extern crate rustc_interface;
#[macro_use]
extern crate rustc_public;

use rustc_public::CrateDef;
use rustc_public::ty::GenericParamDefKind;
use std::ops::ControlFlow;

const CRATE_NAME: &str = "crate_generics";

fn test_generics() -> ControlFlow<()> {
let local_crate = rustc_public::local_crate();

// Check ADT generics
let adts = local_crate.adts();
let my_struct =
adts.iter().find(|adt| adt.trimmed_name() == "MyStruct").expect("Failed to find MyStruct");
let adt_generics = my_struct.generics_of();
assert_eq!(adt_generics.params.len(), 1);
assert_eq!(adt_generics.params[0].name.as_str(), "T");
match &adt_generics.params[0].kind {
GenericParamDefKind::Type { .. } => {}
_ => panic!("Expected type parameter"),
}

// Check Fn generics
let fn_defs = local_crate.fn_defs();
let my_fn = fn_defs
.iter()
.find(|f| f.trimmed_name().as_str() == "my_fn")
.expect("Failed to find my_fn");
let fn_generics = my_fn.generics_of();
assert_eq!(fn_generics.params.len(), 1);
assert_eq!(fn_generics.params[0].name.as_str(), "U");

ControlFlow::Continue(())
}

fn main() {
let path = "generics.rs";
generate_input(&path).unwrap();
let args = &[
"rustc".to_string(),
"--crate-type=lib".to_string(),
"--crate-name".to_string(),
CRATE_NAME.to_string(),
path.to_string(),
];
run!(args, test_generics).unwrap();
}

fn generate_input(path: &str) -> std::io::Result<()> {
std::fs::write(
path,
r#"
pub struct MyStruct<T> {
value: T,
}

pub fn my_fn<U>() {}
"#
)
}
Loading
Loading