Lint non-FFI-safe enums. · rust-lang/rust@25f9534 (original) (raw)

`@@ -145,22 +145,8 @@ fn represent_type_uncached(cx: &mut CrateContext, t: ty::t) -> Repr {

`

145

145

`return Univariant(mk_struct(cx, ftys, packed), dtor)

`

146

146

`}

`

147

147

` ty::ty_enum(def_id, ref substs) => {

`

148

``

`-

struct Case { discr: Disr, tys: ~[ty::t] };

`

149

``

`-

impl Case {

`

150

``

`-

fn is_zerolen(&self, cx: &mut CrateContext) -> bool {

`

151

``

`-

mk_struct(cx, self.tys, false).size == 0

`

152

``

`-

}

`

153

``

`-

fn find_ptr(&self) -> Option {

`

154

``

`-

self.tys.iter().position(|&ty| mono_data_classify(ty) == MonoNonNull)

`

155

``

`-

}

`

156

``

`-

}

`

157

``

-

158

``

`-

let cases = do ty::enum_variants(cx.tcx, def_id).map |vi| {

`

159

``

`-

let arg_tys = do vi.args.map |&raw_ty| {

`

160

``

`-

ty::subst(cx.tcx, substs, raw_ty)

`

161

``

`-

};

`

162

``

`-

Case { discr: vi.disr_val, tys: arg_tys }

`

163

``

`-

};

`

``

148

`+

let cases = get_cases(cx.tcx, def_id, substs);

`

``

149

`+

let hint = ty::lookup_repr_hint(cx.tcx, def_id);

`

164

150

``

165

151

`if cases.len() == 0 {

`

166

152

`// Uninhabitable; represent as unit

`

`@@ -170,7 +156,6 @@ fn represent_type_uncached(cx: &mut CrateContext, t: ty::t) -> Repr {

`

170

156

`if cases.iter().all(|c| c.tys.len() == 0) {

`

171

157

`// All bodies empty -> intlike

`

172

158

`let discrs = cases.map(|c| c.discr);

`

173

``

`-

let hint = ty::lookup_repr_hint(cx.tcx, def_id);

`

174

159

`let bounds = IntBounds {

`

175

160

`ulo: *discrs.iter().min().unwrap(),

`

176

161

`uhi: *discrs.iter().max().unwrap(),

`

`@@ -232,6 +217,56 @@ fn represent_type_uncached(cx: &mut CrateContext, t: ty::t) -> Repr {

`

232

217

`}

`

233

218

`}

`

234

219

``

``

220

`+

/// Determine, without doing translation, whether an ADT must be FFI-safe.

`

``

221

`+

/// For use in lint or similar, where being sound but slightly incomplete is acceptable.

`

``

222

`+

pub fn is_ffi_safe(tcx: ty::ctxt, def_id: ast::DefId) -> bool {

`

``

223

`+

match ty::get(ty::lookup_item_type(tcx, def_id).ty).sty {

`

``

224

`+

ty::ty_enum(def_id, ref substs) => {

`

``

225

`+

let cases = get_cases(tcx, def_id, substs);

`

``

226

`+

// Univariant => like struct/tuple.

`

``

227

`+

if cases.len() <= 2 {

`

``

228

`+

return true;

`

``

229

`+

}

`

``

230

`+

let hint = ty::lookup_repr_hint(tcx, def_id);

`

``

231

`+

// Appropriate representation explicitly selected?

`

``

232

`+

if hint.is_ffi_safe() {

`

``

233

`+

return true;

`

``

234

`+

}

`

``

235

`+

// Conservative approximation of nullable pointers, for Option<~T> etc.

`

``

236

`+

if cases.len() == 2 && hint == attr::ReprAny &&

`

``

237

`+

(cases[0].tys.is_empty() && cases[1].find_ptr().is_some() ||

`

``

238

`+

cases[1].tys.is_empty() && cases[0].find_ptr().is_some()) {

`

``

239

`+

return true;

`

``

240

`+

}

`

``

241

`+

false

`

``

242

`+

}

`

``

243

`+

// struct, tuple, etc.

`

``

244

`+

// (is this right in the present of typedefs?)

`

``

245

`+

_ => true

`

``

246

`+

}

`

``

247

`+

}

`

``

248

+

``

249

`+

// NOTE this should probably all be in ty

`

``

250

`+

struct Case { discr: Disr, tys: ~[ty::t] }

`

``

251

`+

impl Case {

`

``

252

`+

fn is_zerolen(&self, cx: &mut CrateContext) -> bool {

`

``

253

`+

mk_struct(cx, self.tys, false).size == 0

`

``

254

`+

}

`

``

255

`+

fn find_ptr(&self) -> Option {

`

``

256

`+

self.tys.iter().position(|&ty| mono_data_classify(ty) == MonoNonNull)

`

``

257

`+

}

`

``

258

`+

}

`

``

259

+

``

260

`+

fn get_cases(tcx: ty::ctxt, def_id: ast::DefId, substs: &ty::substs) -> ~[Case] {

`

``

261

`+

do ty::enum_variants(tcx, def_id).map |vi| {

`

``

262

`+

let arg_tys = do vi.args.map |&raw_ty| {

`

``

263

`+

ty::subst(tcx, substs, raw_ty)

`

``

264

`+

};

`

``

265

`+

Case { discr: vi.disr_val, tys: arg_tys }

`

``

266

`+

}

`

``

267

`+

}

`

``

268

+

``

269

+

235

270

`fn mk_struct(cx: &mut CrateContext, tys: &[ty::t], packed: bool) -> Struct {

`

236

271

`let lltys = tys.map(|&ty| type_of::sizing_type_of(cx, ty));

`

237

272

`let llty_rec = Type::struct_(lltys, packed);

`