Skip to content

Commit adbd01e

Browse files
Track constness while lowering bounds
1 parent d2aefbb commit adbd01e

File tree

5 files changed

+86
-26
lines changed

5 files changed

+86
-26
lines changed

src/librustc_privacy/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1237,7 +1237,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
12371237
// The traits' privacy in bodies is already checked as a part of trait object types.
12381238
let bounds = rustc_typeck::hir_trait_to_predicates(self.tcx, trait_ref);
12391239

1240-
for (trait_predicate, _) in bounds.trait_bounds {
1240+
for (trait_predicate, _, _) in bounds.trait_bounds {
12411241
if self.visit_trait(*trait_predicate.skip_binder()) {
12421242
return;
12431243
}

src/librustc_typeck/astconv.rs

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use rustc_span::symbol::sym;
3131
use rustc_span::{MultiSpan, Span, DUMMY_SP};
3232
use rustc_target::spec::abi;
3333
use smallvec::SmallVec;
34-
use syntax::ast;
34+
use syntax::ast::{self, Constness};
3535
use syntax::util::lev_distance::find_best_match_for_name;
3636

3737
use std::collections::BTreeSet;
@@ -49,6 +49,8 @@ pub trait AstConv<'tcx> {
4949

5050
fn item_def_id(&self) -> Option<DefId>;
5151

52+
fn default_constness_for_trait_bounds(&self) -> Constness;
53+
5254
/// Returns predicates in scope of the form `X: Foo`, where `X` is
5355
/// a type parameter `X` with the given id `def_id`. This is a
5456
/// subset of the full set of predicates.
@@ -919,6 +921,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
919921
&self,
920922
trait_ref: &hir::TraitRef<'_>,
921923
span: Span,
924+
constness: Constness,
922925
self_ty: Ty<'tcx>,
923926
bounds: &mut Bounds<'tcx>,
924927
speculative: bool,
@@ -947,7 +950,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
947950
);
948951
let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs));
949952

950-
bounds.trait_bounds.push((poly_trait_ref, span));
953+
bounds.trait_bounds.push((poly_trait_ref, span, constness));
951954

952955
let mut dup_bindings = FxHashMap::default();
953956
for binding in &assoc_bindings {
@@ -993,12 +996,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
993996
pub fn instantiate_poly_trait_ref(
994997
&self,
995998
poly_trait_ref: &hir::PolyTraitRef<'_>,
999+
constness: Constness,
9961000
self_ty: Ty<'tcx>,
9971001
bounds: &mut Bounds<'tcx>,
9981002
) -> Option<Vec<Span>> {
9991003
self.instantiate_poly_trait_ref_inner(
10001004
&poly_trait_ref.trait_ref,
10011005
poly_trait_ref.span,
1006+
constness,
10021007
self_ty,
10031008
bounds,
10041009
false,
@@ -1181,18 +1186,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
11811186
let mut trait_bounds = Vec::new();
11821187
let mut region_bounds = Vec::new();
11831188

1189+
let constness = self.default_constness_for_trait_bounds();
11841190
for ast_bound in ast_bounds {
11851191
match *ast_bound {
11861192
hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => {
1187-
trait_bounds.push(b)
1193+
trait_bounds.push((b, constness))
1194+
}
1195+
hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::MaybeConst) => {
1196+
trait_bounds.push((b, Constness::NotConst))
11881197
}
11891198
hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {}
11901199
hir::GenericBound::Outlives(ref l) => region_bounds.push(l),
11911200
}
11921201
}
11931202

1194-
for bound in trait_bounds {
1195-
let _ = self.instantiate_poly_trait_ref(bound, param_ty, bounds);
1203+
for (bound, constness) in trait_bounds {
1204+
let _ = self.instantiate_poly_trait_ref(bound, constness, param_ty, bounds);
11961205
}
11971206

11981207
bounds.region_bounds.extend(
@@ -1226,7 +1235,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
12261235
let mut bounds = Bounds::default();
12271236

12281237
self.add_bounds(param_ty, ast_bounds, &mut bounds);
1229-
bounds.trait_bounds.sort_by_key(|(t, _)| t.def_id());
1238+
bounds.trait_bounds.sort_by_key(|(t, _, _)| t.def_id());
12301239

12311240
bounds.implicitly_sized = if let SizedByDefault::Yes = sized_by_default {
12321241
if !self.is_unsized(ast_bounds, span) { Some(span) } else { None }
@@ -1417,15 +1426,21 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
14171426
let mut potential_assoc_types = Vec::new();
14181427
let dummy_self = self.tcx().types.trait_object_dummy_self;
14191428
for trait_bound in trait_bounds.iter().rev() {
1420-
let cur_potential_assoc_types =
1421-
self.instantiate_poly_trait_ref(trait_bound, dummy_self, &mut bounds);
1429+
let cur_potential_assoc_types = self.instantiate_poly_trait_ref(
1430+
trait_bound,
1431+
Constness::NotConst,
1432+
dummy_self,
1433+
&mut bounds,
1434+
);
14221435
potential_assoc_types.extend(cur_potential_assoc_types.into_iter().flatten());
14231436
}
14241437

14251438
// Expand trait aliases recursively and check that only one regular (non-auto) trait
14261439
// is used and no 'maybe' bounds are used.
1427-
let expanded_traits =
1428-
traits::expand_trait_aliases(tcx, bounds.trait_bounds.iter().cloned());
1440+
let expanded_traits = traits::expand_trait_aliases(
1441+
tcx,
1442+
bounds.trait_bounds.iter().map(|&(a, b, _)| (a.clone(), b)),
1443+
);
14291444
let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) =
14301445
expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
14311446
if regular_traits.len() > 1 {
@@ -1481,16 +1496,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
14811496
let regular_traits_refs_spans = bounds
14821497
.trait_bounds
14831498
.into_iter()
1484-
.filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
1499+
.filter(|(trait_ref, _, _)| !tcx.trait_is_auto(trait_ref.def_id()));
1500+
1501+
for (base_trait_ref, span, constness) in regular_traits_refs_spans {
1502+
assert_eq!(constness, ast::Constness::NotConst);
14851503

1486-
for (base_trait_ref, span) in regular_traits_refs_spans {
14871504
for trait_ref in traits::elaborate_trait_ref(tcx, base_trait_ref) {
14881505
debug!(
14891506
"conv_object_ty_poly_trait_ref: observing object predicate `{:?}`",
14901507
trait_ref
14911508
);
14921509
match trait_ref {
1493-
ty::Predicate::Trait(pred, constness) => {
1510+
ty::Predicate::Trait(pred, _) => {
14941511
associated_types.entry(span).or_default().extend(
14951512
tcx.associated_items(pred.def_id())
14961513
.filter(|item| item.kind == ty::AssocKind::Type)
@@ -2949,7 +2966,7 @@ pub struct Bounds<'tcx> {
29492966

29502967
/// A list of trait bounds. So if you had `T: Debug` this would be
29512968
/// `T: Debug`. Note that the self-type is explicit here.
2952-
pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span)>,
2969+
pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span, Constness)>,
29532970

29542971
/// A list of projection equality bounds. So if you had `T:
29552972
/// Iterator<Item = u32>` this would include `<T as
@@ -2997,11 +3014,10 @@ impl<'tcx> Bounds<'tcx> {
29973014
let outlives = ty::OutlivesPredicate(param_ty, region_bound);
29983015
(ty::Binder::bind(outlives).to_predicate(), span)
29993016
})
3000-
.chain(
3001-
self.trait_bounds
3002-
.iter()
3003-
.map(|&(bound_trait_ref, span)| (bound_trait_ref.to_predicate(), span)),
3004-
)
3017+
.chain(self.trait_bounds.iter().map(|&(bound_trait_ref, span, constness)| {
3018+
let predicate = bound_trait_ref.with_constness(constness).to_predicate();
3019+
(predicate, span)
3020+
}))
30053021
.chain(
30063022
self.projection_bounds
30073023
.iter()

src/librustc_typeck/check/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ pub mod writeback;
9090
use crate::astconv::{AstConv, PathSeg};
9191
use crate::middle::lang_items;
9292
use crate::namespace::Namespace;
93+
use rustc::hir::map::blocks::FnLikeNode;
9394
use rustc::hir::map::Map;
9495
use rustc::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
9596
use rustc::infer::error_reporting::TypeAnnotationNeeded::E0282;
@@ -2612,6 +2613,16 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
26122613
None
26132614
}
26142615

2616+
fn default_constness_for_trait_bounds(&self) -> ast::Constness {
2617+
// FIXME: refactor this into a method
2618+
let node = self.tcx.hir().get(self.body_id);
2619+
if let Some(fn_like) = FnLikeNode::from_node(node) {
2620+
fn_like.constness()
2621+
} else {
2622+
ast::Constness::NotConst
2623+
}
2624+
}
2625+
26152626
fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> {
26162627
let tcx = self.tcx;
26172628
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();

src/librustc_typeck/collect.rs

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use crate::constrained_generic_params as cgp;
2020
use crate::lint;
2121
use crate::middle::resolve_lifetime as rl;
2222
use crate::middle::weak_lang_items;
23+
use rustc::hir::map::blocks::FnLikeNode;
2324
use rustc::hir::map::Map;
2425
use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
2526
use rustc::mir::mono::Linkage;
@@ -288,6 +289,22 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
288289
Some(self.item_def_id)
289290
}
290291

292+
fn default_constness_for_trait_bounds(&self) -> ast::Constness {
293+
// FIXME: refactor this into a method
294+
let hir_id = self
295+
.tcx
296+
.hir()
297+
.as_local_hir_id(self.item_def_id)
298+
.expect("Non-local call to local provider is_const_fn");
299+
300+
let node = self.tcx.hir().get(hir_id);
301+
if let Some(fn_like) = FnLikeNode::from_node(node) {
302+
fn_like.constness()
303+
} else {
304+
ast::Constness::NotConst
305+
}
306+
}
307+
291308
fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> {
292309
self.tcx.at(span).type_param_predicates((self.item_def_id, def_id))
293310
}
@@ -454,6 +471,7 @@ impl ItemCtxt<'tcx> {
454471
ty: Ty<'tcx>,
455472
only_self_bounds: OnlySelfBounds,
456473
) -> Vec<(ty::Predicate<'tcx>, Span)> {
474+
let constness = self.default_constness_for_trait_bounds();
457475
let from_ty_params = ast_generics
458476
.params
459477
.iter()
@@ -462,7 +480,7 @@ impl ItemCtxt<'tcx> {
462480
_ => None,
463481
})
464482
.flat_map(|bounds| bounds.iter())
465-
.flat_map(|b| predicates_from_bound(self, ty, b));
483+
.flat_map(|b| predicates_from_bound(self, ty, b, constness));
466484

467485
let from_where_clauses = ast_generics
468486
.where_clause
@@ -482,7 +500,7 @@ impl ItemCtxt<'tcx> {
482500
};
483501
bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b)))
484502
})
485-
.flat_map(|(bt, b)| predicates_from_bound(self, bt, b));
503+
.flat_map(|(bt, b)| predicates_from_bound(self, bt, b, constness));
486504

487505
from_ty_params.chain(from_where_clauses).collect()
488506
}
@@ -2107,6 +2125,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
21072125
let mut is_default_impl_trait = None;
21082126

21092127
let icx = ItemCtxt::new(tcx, def_id);
2128+
let constness = icx.default_constness_for_trait_bounds();
21102129

21112130
const NO_GENERICS: &hir::Generics<'_> = &hir::Generics::empty();
21122131

@@ -2308,11 +2327,18 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
23082327

23092328
for bound in bound_pred.bounds.iter() {
23102329
match bound {
2311-
&hir::GenericBound::Trait(ref poly_trait_ref, _) => {
2330+
&hir::GenericBound::Trait(ref poly_trait_ref, modifier) => {
2331+
let constness = match modifier {
2332+
hir::TraitBoundModifier::MaybeConst => ast::Constness::NotConst,
2333+
hir::TraitBoundModifier::None => constness,
2334+
hir::TraitBoundModifier::Maybe => bug!("this wasn't handled"),
2335+
};
2336+
23122337
let mut bounds = Bounds::default();
23132338
let _ = AstConv::instantiate_poly_trait_ref(
23142339
&icx,
23152340
poly_trait_ref,
2341+
constness,
23162342
ty,
23172343
&mut bounds,
23182344
);
@@ -2488,19 +2514,25 @@ fn predicates_from_bound<'tcx>(
24882514
astconv: &dyn AstConv<'tcx>,
24892515
param_ty: Ty<'tcx>,
24902516
bound: &'tcx hir::GenericBound<'tcx>,
2517+
constness: ast::Constness,
24912518
) -> Vec<(ty::Predicate<'tcx>, Span)> {
24922519
match *bound {
2493-
hir::GenericBound::Trait(ref tr, hir::TraitBoundModifier::None) => {
2520+
hir::GenericBound::Trait(ref tr, modifier) => {
2521+
let constness = match modifier {
2522+
hir::TraitBoundModifier::Maybe => return vec![],
2523+
hir::TraitBoundModifier::MaybeConst => ast::Constness::NotConst,
2524+
hir::TraitBoundModifier::None => constness,
2525+
};
2526+
24942527
let mut bounds = Bounds::default();
2495-
let _ = astconv.instantiate_poly_trait_ref(tr, param_ty, &mut bounds);
2528+
let _ = astconv.instantiate_poly_trait_ref(tr, constness, param_ty, &mut bounds);
24962529
bounds.predicates(astconv.tcx(), param_ty)
24972530
}
24982531
hir::GenericBound::Outlives(ref lifetime) => {
24992532
let region = astconv.ast_region_to_region(lifetime, None);
25002533
let pred = ty::Binder::bind(ty::OutlivesPredicate(param_ty, region));
25012534
vec![(ty::Predicate::TypeOutlives(pred), lifetime.span)]
25022535
}
2503-
hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => vec![],
25042536
}
25052537
}
25062538

src/librustc_typeck/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ pub fn hir_trait_to_predicates<'tcx>(
382382
&item_cx,
383383
hir_trait,
384384
DUMMY_SP,
385+
syntax::ast::Constness::NotConst,
385386
tcx.types.err,
386387
&mut bounds,
387388
true,

0 commit comments

Comments
 (0)