mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-26 06:35:27 +00:00
ensure projections are prohibited when type parameters are
Technically a [breaking-change], but the broken code is useless, like `i32<Param=()>`. Fixes #24682
This commit is contained in:
parent
a41d4359c5
commit
5d4455510a
@ -1895,6 +1895,7 @@ register_diagnostics! {
|
||||
// E0006 // merged with E0005
|
||||
// E0134,
|
||||
// E0135,
|
||||
E0229, // associated type bindings are not allowed here
|
||||
E0264, // unknown external lang item
|
||||
E0278, // requirement is not satisfied
|
||||
E0279, // requirement is not satisfied
|
||||
|
@ -16,36 +16,40 @@
|
||||
|
||||
use middle::def;
|
||||
use middle::ty::{self, Ty};
|
||||
|
||||
use syntax::codemap::Span;
|
||||
use rustc_front::hir as ast;
|
||||
|
||||
pub const NO_REGIONS: usize = 1;
|
||||
pub const NO_TPS: usize = 2;
|
||||
|
||||
pub fn check_path_args(tcx: &ty::ctxt, segments: &[ast::PathSegment], flags: usize) {
|
||||
pub fn prohibit_type_params(tcx: &ty::ctxt, segments: &[ast::PathSegment]) {
|
||||
for segment in segments {
|
||||
if (flags & NO_TPS) != 0 {
|
||||
for typ in segment.parameters.types() {
|
||||
span_err!(tcx.sess, typ.span, E0109,
|
||||
"type parameters are not allowed on this type");
|
||||
break;
|
||||
}
|
||||
for typ in segment.parameters.types() {
|
||||
span_err!(tcx.sess, typ.span, E0109,
|
||||
"type parameters are not allowed on this type");
|
||||
break;
|
||||
}
|
||||
|
||||
if (flags & NO_REGIONS) != 0 {
|
||||
for lifetime in segment.parameters.lifetimes() {
|
||||
span_err!(tcx.sess, lifetime.span, E0110,
|
||||
"lifetime parameters are not allowed on this type");
|
||||
break;
|
||||
}
|
||||
for lifetime in segment.parameters.lifetimes() {
|
||||
span_err!(tcx.sess, lifetime.span, E0110,
|
||||
"lifetime parameters are not allowed on this type");
|
||||
break;
|
||||
}
|
||||
for binding in segment.parameters.bindings() {
|
||||
prohibit_projection(tcx, binding.span);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn prohibit_projection(tcx: &ty::ctxt, span: Span)
|
||||
{
|
||||
span_err!(tcx.sess, span, E0229,
|
||||
"associated type bindings are not allowed here");
|
||||
}
|
||||
|
||||
pub fn prim_ty_to_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
segments: &[ast::PathSegment],
|
||||
nty: ast::PrimTy)
|
||||
-> Ty<'tcx> {
|
||||
check_path_args(tcx, segments, NO_TPS | NO_REGIONS);
|
||||
prohibit_type_params(tcx, segments);
|
||||
match nty {
|
||||
ast::TyBool => tcx.types.bool,
|
||||
ast::TyChar => tcx.types.char,
|
||||
|
@ -48,7 +48,7 @@
|
||||
//! case but `&a` in the second. Basically, defaults that appear inside
|
||||
//! an rptr (`&r.T`) use the region `r` that appears in the rptr.
|
||||
|
||||
use middle::astconv_util::{prim_ty_to_ty, check_path_args, NO_TPS, NO_REGIONS};
|
||||
use middle::astconv_util::{prim_ty_to_ty, prohibit_type_params, prohibit_projection};
|
||||
use middle::const_eval::{self, ConstVal};
|
||||
use middle::const_eval::EvalHint::UncheckedExprHint;
|
||||
use middle::def;
|
||||
@ -1210,7 +1210,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||
|
||||
debug!("associated_path_def_to_ty: {:?}::{}", ty, assoc_name);
|
||||
|
||||
check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS);
|
||||
prohibit_type_params(tcx, slice::ref_slice(item_segment));
|
||||
|
||||
// Find the type of the associated item, and the trait where the associated
|
||||
// item is declared.
|
||||
@ -1312,7 +1312,7 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||
{
|
||||
let tcx = this.tcx();
|
||||
|
||||
check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS);
|
||||
prohibit_type_params(tcx, slice::ref_slice(item_segment));
|
||||
|
||||
let self_ty = if let Some(ty) = opt_self_ty {
|
||||
ty
|
||||
@ -1401,7 +1401,7 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||
base_segments.last().unwrap(),
|
||||
&mut projection_bounds);
|
||||
|
||||
check_path_args(tcx, base_segments.split_last().unwrap().1, NO_TPS | NO_REGIONS);
|
||||
prohibit_type_params(tcx, base_segments.split_last().unwrap().1);
|
||||
trait_ref_to_object_type(this,
|
||||
rscope,
|
||||
span,
|
||||
@ -1410,7 +1410,7 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||
&[])
|
||||
}
|
||||
def::DefTy(did, _) | def::DefStruct(did) => {
|
||||
check_path_args(tcx, base_segments.split_last().unwrap().1, NO_TPS | NO_REGIONS);
|
||||
prohibit_type_params(tcx, base_segments.split_last().unwrap().1);
|
||||
ast_path_to_ty(this,
|
||||
rscope,
|
||||
span,
|
||||
@ -1419,12 +1419,12 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||
base_segments.last().unwrap())
|
||||
}
|
||||
def::DefTyParam(space, index, _, name) => {
|
||||
check_path_args(tcx, base_segments, NO_TPS | NO_REGIONS);
|
||||
prohibit_type_params(tcx, base_segments);
|
||||
tcx.mk_param(space, index, name)
|
||||
}
|
||||
def::DefSelfTy(_, Some((_, self_ty_id))) => {
|
||||
// Self in impl (we know the concrete type).
|
||||
check_path_args(tcx, base_segments, NO_TPS | NO_REGIONS);
|
||||
prohibit_type_params(tcx, base_segments);
|
||||
if let Some(&ty) = tcx.ast_ty_to_ty_cache.borrow().get(&self_ty_id) {
|
||||
if let Some(free_substs) = this.get_free_substs() {
|
||||
ty.subst(tcx, free_substs)
|
||||
@ -1437,11 +1437,11 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||
}
|
||||
def::DefSelfTy(Some(_), None) => {
|
||||
// Self in trait.
|
||||
check_path_args(tcx, base_segments, NO_TPS | NO_REGIONS);
|
||||
prohibit_type_params(tcx, base_segments);
|
||||
tcx.mk_self_type()
|
||||
}
|
||||
def::DefAssociatedTy(trait_did, _) => {
|
||||
check_path_args(tcx, &base_segments[..base_segments.len()-2], NO_TPS | NO_REGIONS);
|
||||
prohibit_type_params(tcx, &base_segments[..base_segments.len()-2]);
|
||||
qpath_to_ty(this,
|
||||
rscope,
|
||||
span,
|
||||
@ -2191,8 +2191,7 @@ fn prohibit_projections<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
bindings: &[ConvertedBinding<'tcx>])
|
||||
{
|
||||
for binding in bindings.iter().take(1) {
|
||||
span_err!(tcx.sess, binding.span, E0229,
|
||||
"associated type bindings are not allowed here");
|
||||
prohibit_projection(tcx, binding.span);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ use self::TupleArgumentsFlag::*;
|
||||
use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv, PathParamMode};
|
||||
use check::_match::pat_ctxt;
|
||||
use fmt_macros::{Parser, Piece, Position};
|
||||
use middle::astconv_util::{check_path_args, NO_TPS, NO_REGIONS};
|
||||
use middle::astconv_util::prohibit_type_params;
|
||||
use middle::def;
|
||||
use middle::def_id::{DefId, LOCAL_CRATE};
|
||||
use middle::infer;
|
||||
@ -4535,8 +4535,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
for (opt_space, segment) in segment_spaces.iter().zip(segments) {
|
||||
match *opt_space {
|
||||
None => {
|
||||
check_path_args(fcx.tcx(), slice::ref_slice(segment),
|
||||
NO_TPS | NO_REGIONS);
|
||||
prohibit_type_params(fcx.tcx(), slice::ref_slice(segment));
|
||||
}
|
||||
|
||||
Some(space) => {
|
||||
|
@ -3294,7 +3294,6 @@ register_diagnostics! {
|
||||
E0226, // only a single explicit lifetime bound is permitted
|
||||
E0227, // ambiguous lifetime bound, explicit lifetime bound required
|
||||
E0228, // explicit lifetime bound required
|
||||
E0229, // associated type bindings are not allowed here
|
||||
E0230, // there is no type parameter on trait
|
||||
E0231, // only named substitution parameters are allowed
|
||||
// E0233,
|
||||
|
31
src/test/compile-fail/issue-24682.rs
Normal file
31
src/test/compile-fail/issue-24682.rs
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
trait A: Sized {
|
||||
type N;
|
||||
fn x() ->
|
||||
Self<
|
||||
N= //~ ERROR associated type bindings are not allowed here
|
||||
Self::N> {
|
||||
loop {}
|
||||
}
|
||||
fn y(&self) ->
|
||||
std
|
||||
<N=()> //~ ERROR associated type bindings are not allowed here
|
||||
::option::Option<()>
|
||||
{ None }
|
||||
fn z(&self) ->
|
||||
u32<N=()> //~ ERROR associated type bindings are not allowed here
|
||||
{ 42 }
|
||||
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
Loading…
Reference in New Issue
Block a user