Skip to content

Commit 6762d9d

Browse files
thunderseethecopybara-github
authored andcommitted
Fix crosstool breakges.
This CL fixes two issues: * Index didn't correctly handle when it's element type was a reference * Trait aliases to generic traits aren't supported (because you can't using a template). It adds tests for the two behaviors. PiperOrigin-RevId: 896148746
1 parent fed62f4 commit 6762d9d

File tree

9 files changed

+212
-50
lines changed

9 files changed

+212
-50
lines changed

cc_bindings_from_rs/generate_bindings/database/fully_qualified_name.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ pub struct ExportedPath {
126126
/// True if any segment of this path is marked #[doc(hidden)] making it a less preferable path
127127
/// than any non-hidden path regardless of length.
128128
pub is_doc_hidden: bool,
129+
/// True if this path is a reexport.
130+
pub is_reexport: bool,
129131
/// The crate that defines this path.
130132
pub krate: CrateNum,
131133
}
@@ -166,6 +168,12 @@ impl Ord for ExportedPath {
166168
(None, Some(_)) => Ordering::Less,
167169
_ => Ordering::Equal,
168170
})
171+
// Between two paths of the same length, prefer the one that is not a reexport.
172+
.then_with(|| match (self.is_reexport, other.is_reexport) {
173+
(true, false) => Ordering::Greater,
174+
(false, true) => Ordering::Less,
175+
_ => Ordering::Equal,
176+
})
169177
// Failing all else, choose the lexicographically smallest path.
170178
.then_with(|| self.path.cmp(&other.path))
171179
.then_with(|| self.name.as_str().cmp(other.name.as_str()))

cc_bindings_from_rs/generate_bindings/format_type.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,7 @@ pub fn region_is_elided<'tcx>(tcx: TyCtxt<'tcx>, region: ty::Region<'tcx>) -> bo
594594
}
595595
}
596596

597+
#[derive(Debug, Clone)]
597598
pub struct CcParamTy<'tcx> {
598599
pub snippet: CcSnippet<'tcx>,
599600
pub is_lifetime_bound: bool,

cc_bindings_from_rs/generate_bindings/generate_struct_and_union.rs

Lines changed: 43 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ extern crate rustc_middle;
88
extern crate rustc_span;
99

1010
use crate::format_cc_ident;
11-
use crate::format_type::CcParamTy;
11+
use crate::format_type::{format_param_types_for_cc, CcParamTy};
1212
use crate::generate_doc_comment;
1313
use crate::generate_function::{
1414
format_variant_ctor_cc_name, generate_thunk_call, Param, ThunkSelfParameter,
@@ -26,12 +26,17 @@ use database::{AdtCoreBindings, BindingsGenerator, TypeLocation};
2626
use error_report::{anyhow, bail, ensure};
2727
use itertools::Itertools;
2828
use proc_macro2::{Ident, Literal, TokenStream};
29-
use query_compiler::post_analysis_typing_env;
29+
use query_compiler::{
30+
liberate_and_deanonymize_late_bound_regions, post_analysis_typing_env, try_normalize,
31+
};
3032
use quote::{format_ident, quote};
3133
use rustc_abi::{Endian, FieldsShape, VariantIdx, Variants};
34+
use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
3235
use rustc_middle::mir::interpret::Scalar;
3336
use rustc_middle::mir::ConstValue;
34-
use rustc_middle::ty::{self, AssocKind, IntTy, Ty, TyCtxt, TyKind, TypeFlags, TypingEnv, UintTy};
37+
use rustc_middle::ty::{
38+
self, AssocKind, IntTy, Region, Ty, TyCtxt, TyKind, TypeFlags, TypingEnv, TypingMode, UintTy,
39+
};
3540
use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
3641
use rustc_span::symbol::sym;
3742
use std::collections::{BTreeSet, HashMap, HashSet};
@@ -574,7 +579,7 @@ fn generate_index_impls<'tcx>(
574579

575580
let query_index_impls = |index_trait: DefId,
576581
method_this_qualifier: TokenStream,
577-
to_ref: fn(TyCtxt<'tcx>, Ty<'tcx>) -> Ty<'tcx>|
582+
to_ref: fn(TyCtxt<'tcx>, Region<'tcx>, Ty<'tcx>) -> Ty<'tcx>|
578583
-> IndexImpls<'tcx> {
579584
let mut has_usize_impl = false;
580585
let mut has_isize_impl = false;
@@ -588,32 +593,37 @@ fn generate_index_impls<'tcx>(
588593
.expect("DefId for an `Index` trait impl lacked a trait header");
589594
// Index 0 of our trait ref is the self type, so index 1 is the type we're converting
590595
// into.
591-
let index_element_ty =
592-
middle_trait_header.trait_ref.instantiate_identity().args.type_at(1);
596+
let trait_args = middle_trait_header.trait_ref.instantiate_identity().args;
597+
let index_element_ty = trait_args.type_at(1);
598+
if index_element_ty.flags().intersects(has_type_or_const_vars()) {
599+
return Err((anyhow!("Index trait impl has uninstantiated generic parameters, which is not yet supported {index_element_ty}"), index_impl_id));
600+
}
593601

594602
if index_element_ty.is_usize() {
595603
has_usize_impl = true;
596604
} else if matches!(index_element_ty.kind(), TyKind::Int(IntTy::Isize)) {
597605
has_isize_impl = true;
598606
}
599-
let index_cc_ty = db
600-
.format_ty_for_cc(index_element_ty, TypeLocation::FnParam { is_self_param: false, elided_is_output: false })
601-
.map_err(|e| (e, index_impl_id))?;
602607

603-
let index_assoc_fn = tcx.associated_items(index_impl_id)
608+
let index_trait_assoc_fn = tcx.associated_items(index_trait)
604609
.in_definition_order()
605610
.filter(|assoc_item| matches!(assoc_item.kind, AssocKind::Fn { .. }))
606611
// For `Index` or `IndexMut`, we expect exactly one associated fn.
607612
.exactly_one()
608-
.map_err(|_| (anyhow!("{} impl expected to have a single function", tcx.def_path_str(index_trait)), index_impl_id))?;
609-
610-
let output_unnorm = tcx.fn_sig(index_assoc_fn.def_id)
611-
// Assuming that the impl is monomorphic but we might need to provide substs here.
612-
.instantiate_identity()
613-
.output();
614-
let output_ty = tcx.normalize_erasing_late_bound_regions(
615-
TypingEnv::fully_monomorphized(),
616-
output_unnorm);
613+
.map_err(|_| (anyhow!("{} impl expected to have a single function", tcx.def_path_str(index_trait)), index_trait))?;
614+
615+
let unnorm_fn_sig =
616+
liberate_and_deanonymize_late_bound_regions(
617+
tcx,
618+
tcx.fn_sig(index_trait_assoc_fn.def_id).instantiate(tcx, trait_args),
619+
index_trait_assoc_fn.def_id);
620+
println!("unnorm_fn_sig: {:?}", unnorm_fn_sig);
621+
let fn_sig = try_normalize(tcx,
622+
ty::PseudoCanonicalInput {
623+
typing_env: TypingEnv::fully_monomorphized(),
624+
value: unnorm_fn_sig,
625+
}).expect("Please file a bug at crubit.rs-bug. We failed to normalize the function signature of an `Index` impl.");
626+
let output_ty = fn_sig.output();
617627

618628
// Index::Output isn't the real return type of our index method. We need to wrap it in a
619629
// reference before formatting, so that Output types like `str` are formatted correctly as
@@ -644,16 +654,13 @@ fn generate_index_impls<'tcx>(
644654
let cc_thunk_decls = cc_thunk_decls.into_tokens(&mut prereqs);
645655
let doc_comment = generate_doc_comment(db, index_impl_id);
646656

647-
let self_by_ref = to_ref(tcx, core.self_ty);
648-
let self_cpp_ty = db
649-
.format_ty_for_cc(
650-
self_by_ref,
651-
TypeLocation::FnParam { is_self_param: true, elided_is_output: true },
652-
)
653-
.expect(
654-
"ADT's self type should be C++-convertible after generate_adt_core succeeds",
655-
);
656-
let self_cpp_ty = self_cpp_ty.into_tokens(&mut prereqs);
657+
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
658+
let lifetime = infcx.next_region_var(RegionVariableOrigin::Autoref(tcx.def_span(index_impl_id)));
659+
660+
let self_by_ref = to_ref(tcx, lifetime, core.self_ty);
661+
// We know index has two params, and we use that assumption below to construct our
662+
// &[Param] slice with direct indexing.
663+
let params = format_param_types_for_cc(db, &fn_sig, /*has_self_param=*/ true).map_err(|e| (e, index_impl_id))?;
657664
let impl_body = generate_thunk_call(
658665
db,
659666
index_impl_id,
@@ -666,22 +673,16 @@ fn generate_index_impls<'tcx>(
666673
),
667674
&[Param {
668675
cc_name: format_ident!("self"),
669-
cpp_type: CcParamTy {
670-
snippet: CcSnippet::new(self_cpp_ty),
671-
is_lifetime_bound: false,
672-
},
673-
ty: self_by_ref,
676+
cpp_type: params[0].clone(),
677+
ty: fn_sig.inputs()[0],
674678
}, Param {
675679
cc_name: format_ident!("index"),
676-
cpp_type: CcParamTy {
677-
snippet: index_cc_ty.clone(),
678-
is_lifetime_bound: false,
679-
},
680-
ty: index_element_ty,
680+
cpp_type: params[1].clone(),
681+
ty: fn_sig.inputs()[1],
681682
}],
682683
).map_err(|e| (e, index_impl_id))?;
683684

684-
let index_cc_ty = index_cc_ty.into_tokens(&mut prereqs);
685+
let index_cc_ty = params[1].snippet.clone().into_tokens(&mut prereqs);
685686
let impl_body_tokens = impl_body.into_tokens(&mut prereqs);
686687
prereqs.move_defs_to_fwd_decls();
687688

@@ -716,12 +717,12 @@ fn generate_index_impls<'tcx>(
716717
let index_impls: IndexImpls<'tcx> = query_index_impls(
717718
tcx.lang_items().index_trait().expect("Could not find Index trait"),
718719
quote! { const& },
719-
|tcx, ty| Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, ty),
720+
Ty::new_imm_ref,
720721
);
721722
let index_mut_impls: IndexImpls<'tcx> = query_index_impls(
722723
tcx.lang_items().index_mut_trait().expect("Could not find IndexMut trait"),
723724
quote! { & },
724-
|tcx, ty| Ty::new_mut_ref(tcx, tcx.lifetimes.re_static, ty),
725+
Ty::new_mut_ref,
725726
);
726727

727728
index_impls.into_iter(db).chain(index_mut_impls.into_iter(db)).collect()

cc_bindings_from_rs/generate_bindings/lib.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,7 @@ fn public_paths_by_def_id(
499499
name: child.ident.name,
500500
type_alias_def_id,
501501
is_doc_hidden,
502+
is_reexport: !child.reexport_chain.is_empty(),
502503
krate: crate_num,
503504
};
504505
use std::collections::hash_map::Entry;
@@ -873,6 +874,21 @@ fn generate_using<'tcx>(
873874
tcx.def_path_str(def_id)
874875
)
875876
}
877+
let generics = tcx.generics_of(def_id);
878+
// Traits do not support const generics.
879+
let generic_ty_args_count = generics
880+
.own_params
881+
.iter()
882+
.filter(|param| matches!(param.kind, GenericParamDefKind::Type { .. }))
883+
.count();
884+
let has_generic_ty_args = if generics.has_self {
885+
generic_ty_args_count > 1
886+
} else {
887+
generic_ty_args_count > 0
888+
};
889+
if has_generic_ty_args {
890+
bail!("Aliases to generic trait `{}` are not supported.", tcx.def_path_str(def_id))
891+
}
876892
let canonical_name = db.symbol_canonical_name(def_id).expect(
877893
"generate_trait was unexpectedly called on an item without a canonical name",
878894
);

cc_bindings_from_rs/test/known_traits/index/rs_index.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,18 @@ impl IndexMut<(usize, usize)> for Map {
123123
&mut self.data[index.0 * self.row_size + index.1]
124124
}
125125
}
126+
127+
pub struct Id(pub i32);
128+
impl Id {
129+
pub fn new(id: i32) -> Self {
130+
Self(id)
131+
}
132+
}
133+
134+
impl Index<&Id> for Map {
135+
type Output = str;
136+
137+
fn index(&self, _index: &Id) -> &Self::Output {
138+
&self.data[0]
139+
}
140+
}

0 commit comments

Comments
 (0)